2014-04-02 45 views
0

雖然代碼正在編譯並正確顯示輸出,但是當我運行「valgrind」時,它顯示以下錯誤。因爲我沒有valgrind的背景知識,所以我很難理解這一點。代碼中的內存錯誤和可能的解決方案

Invalid write of size 1 
==14657== at 0x4EAE10C: _IO_default_xsputn (genops.c:480) 
==14657== by 0x4E7CF81: vfprintf (vfprintf.c:1630) 
==14657== by 0x4EA3813: vsprintf (iovsprintf.c:43) 
==14657== by 0x4E85A06: sprintf (sprintf.c:34) 
==14657== by 0x400622: copy_id_name (assign2a.c:12) 
==14657== by 0x40065E: main (assign2a.c:21) 
==14657== Address 0x51f204b is 0 bytes after a block of size 11 alloc'd 
==14657== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==14657== by 0x400600: copy_id_name (assign2a.c:11) 
==14657== by 0x40065E: main (assign2a.c:21) 
==14657== 

請解釋一下實際的錯誤和解決方法是什麼,以消除此錯誤。

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

/** Returns a pointer to allocated memory containing string in form "<id>=<name>" */ 
char *copy_id_name(const char *id, const char *name) { 
    char *ptr = NULL; 
    size_t len; 
    // Compute required length 
    len = strlen(id) + strlen(name); // [sic] 
    ptr = malloc(len-2); // [sic] 
    sprintf(ptr, "%s=%s", id, name); 
    return ptr; 
} 


int main(int argc, char *argv[]) 
{ 
    char *ptr; 

    if (argc > 2) { 
    ptr = copy_id_name(argv[1], argv[2]); 
    } else { 
    ptr = copy_id_name("666", "badname"); 
    } 
    printf("result: [%s]\n", ptr); 
    return 0; 
} 
+0

你的valgrind選項是什麼? – vad

回答

3

首先您必須記住,C中的字符串實際上比strlen報告的字符長一個字符。該額外的字符用於特殊字符('\0'),告訴函數它是字符串的結尾。

這裏的問題是,你是分配比idname串的組合長度的兩個字節,然後合併這些字符串具有兩個加入字符('='和終止'\0')。這意味着你將在分配內存的末尾寫入數據。

+0

即使在從malloc(len)更改爲malloc(len + 2)之後,valgrind也會顯示與上述相同的錯誤:( – akshitonline

+1

@ user3425724只需驗證一下,在程序中添加一個調試printf調用,分配(例如'printf(「分配%d個字節\ n」,len + 2);')如果長度不是'12'(字符串爲「666」和「badname」 )然後你沒有向我們顯示正確的代碼 –

+0

運行了錯誤的文件問題已解決謝謝:) – akshitonline

2
ptr = malloc(len-2); 

您分配4個字節比需要少。 strlen()給出了一個字符串的長度並且不計算空終止。但是,您需要爲空終止分配空間。只需將-2更改爲+2。

+0

即使從malloc(len)更改爲malloc(len + 2)之後,valgrind也顯示與上面提到:( – akshitonline

+0

問題已解決。謝謝:) – akshitonline