2011-12-24 76 views
1

我對C很新,並且在做玩具程序來學習它。 下面的代碼編譯,正確地輸出,但Valgrind的報告內存泄漏:malloc char *裏面的函數,valgrind報告內存泄漏

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

void add_vertex(vertex *v_p, char *name) { 
    if(strlen(name) == 0) { 
     printf("error"); 
    } 
    v_p->name = (char *)malloc(strlen(name) + 1); 
    if(v_p->name == NULL) { 
     printf("error"); 
    } 
    strcpy(v_p->name, name); 
    v_p->cluster = -1; 
    v_p->deleted = 0; 
    printf("added vertex.\n"); 
} 

void free_vertex(vertex *ver) { 
    if(ver->name) {free(ver->name);printf("free'd name\n");} 
    free(ver); 

} 

int main() { 
    int Nu = 0; 
    vertex *arr = (vertex *)malloc(2 * sizeof(vertex)); 
    vertex *_temp; 
    int i =0; 
    add_vertex(arr, "Hello"); 
    add_vertex(arr+1, "World"); 
    _temp = (vertex *)realloc(arr, 4*sizeof(vertex)); 
    printf("reallocated\n"); 
    if (_temp != NULL) { 
     arr = _temp; 
     add_vertex(arr+2, "this"); 
     add_vertex(arr +3, "worked"); 
     Nu=4; 
    } 
    else{ 
     printf("FAIL\n"); 
     Nu=2; 
    } 
    for (; i <Nu; i++) { 
     printf("%s\n",(arr+i)->name); 
    } 
    for (; i <Nu; i++) { 
     free_vertex(arr+i); 
    } 
    free(arr); 
    return 0; 
} 

的頂點在頭文件中的編碼,

typedef struct vertex_t 
{ 
    char* name; 
    int  cluster; 
    int deleted; 
}vertex 

的輸出是:

added vertex. 
added vertex. 
reallocated 
added vertex. 
added vertex. 
Hello 
World 
this 
worked 

它不打印「free'd記憶」,所以它在哪裏free'd? 這裏是Valgrind的不得不說一下吧:

==1436== HEAP SUMMARY: 
==1436==  in use at exit: 24 bytes in 4 blocks 
==1436== total heap usage: 6 allocs, 2 frees, 120 bytes allocated 
==1436== 
==1436== 5 bytes in 1 blocks are definitely lost in loss record 1 of 4 
==1436== at 0x4C2893D: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==1436== by 0x4006C3: add_vertex (graph.c:10) 
==1436== by 0x4007EF: main (graph.c:37) 
==1436== 
==1436== 6 bytes in 1 blocks are definitely lost in loss record 2 of 4 
==1436== at 0x4C2893D: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==1436== by 0x4006C3: add_vertex (graph.c:10) 
==1436== by 0x400797: main (graph.c:31) 
==1436== 
==1436== 6 bytes in 1 blocks are definitely lost in loss record 3 of 4 
==1436== at 0x4C2893D: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==1436== by 0x4006C3: add_vertex (graph.c:10) 
==1436== by 0x4007AC: main (graph.c:32) 
==1436== 
==1436== 7 bytes in 1 blocks are definitely lost in loss record 4 of 4 
==1436== at 0x4C2893D: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==1436== by 0x4006C3: add_vertex (graph.c:10) 
==1436== by 0x400804: main (graph.c:38) 
==1436== 
==1436== LEAK SUMMARY: 
==1436== definitely lost: 24 bytes in 4 blocks 
==1436== indirectly lost: 0 bytes in 0 blocks 
==1436==  possibly lost: 0 bytes in 0 blocks 
==1436== still reachable: 0 bytes in 0 blocks 
==1436==   suppressed: 0 bytes in 0 blocks 

什麼是代碼中的問題?我應該分配不同的頂點名稱嗎? 感謝您的幫助!

編輯:感謝你們所有人!我已經固定的代碼,我現在不釋放單個元素,即

void free_vertex(vertex *ver) { 
    if(ver->name) {free(ver->name);printf("free'd name\n");} 
} 

當然和我重新設置爲0,不能相信我忽略了它。非常感謝!

回答

5

您不會在釋放代碼的循環中重置i。這些循環應該是這樣的:

for (i = 0; i <Nu; i++) { 
    printf("%s\n",(arr+i)->name); 
} 
for (i = 0; i <Nu; i++) { 
    free_vertex(arr+i); 
} 

添加了另一個觀點:

free_vertex()不應該有:

free(ver) 

線,這是別人在說什麼。

free_vertex()和add_vertex()應該是並行的,意思是釋放只釋放add中分配的內容。

+2

這是真的 - 但是固定,這將嚴重打破的malloc - 因爲程序會釋放所有未malloced事情。 – 2011-12-24 11:47:02

4

realloc在這裏是無關緊要的。你這樣做:

arr = malloc(4 * sizeof(vertex)); 
for (int i = 0; i < 4; ++i) { 
    free(arr[i]); 
} 
free(arr); 

你不應該釋放數組的單個元素。

+2

弗朗西斯的回答是正確的,但這是潛伏的第二個錯誤。 – 2011-12-24 11:43:27

2

你不能free不完全相同的一個你mallocrealloc回來,等等。這是不確定的行爲,你問堆損壞或更壞,如果你做到這一點以外的任何指針。

(有趣的部分:由於arr+0等於arr,一旦你正確地重新初始化iFrancis's answer提到,通過循環的第一次迭代釋放整個陣列從此,你遍歷數組不再是那個存在,這是本身未定義的行爲。)

2

你必須mallocfree一樣的東西!

你是mallocrealloc一個數組,所以你必須釋放數組。 您正在釋放各個頂點。

2

問題可能是因爲下面的代碼i未初始化爲零!

for (; i <Nu; i++) { 
    printf("%s\n",(arr+i)->name); 
} 
for (; i <Nu; i++) { 
    free_vertex(arr+i); 
} 

所以應該

for (; i <Nu; i++) { 
    printf("%s\n",(arr+i)->name); 
} 
for (i=0 ; i <Nu; i++) { 
    free_vertex(arr+i); 
} 
+0

@cHao這是一個好點!我喜歡「它應該被扔掉」的部分! :) – 2011-12-24 12:15:24