2011-12-24 77 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