我对C很陌生,正在做玩具程序来学习它。 以下代码编译,输出正确,但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 memory”,所以它在哪里免费? 这是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");}
}
当然重新将i设置为0.不能相信我忽略了它。非常感谢!
答案 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()应该是并行的,即free只释放add中分配的内容。
答案 1 :(得分:4)
realloc在这里无关紧要。你这样做了:
arr = malloc(4 * sizeof(vertex));
for (int i = 0; i < 4; ++i) {
free(arr[i]);
}
free(arr);
你不应该释放数组中的单个元素。
答案 2 :(得分:2)
你不能free
除malloc
,realloc
之类的完全相同的指针之外的任何指针。这是未定义的行为,你要求堆损坏或者更糟,如果你这样做。
(有趣的部分:由于arr+0
等于arr
,一旦你按照Francis's answer中的提法正确重新启动i
,循环的第一次迭代将释放整个数组从那时起,你将迭代一个不再存在的数组,这本身就是未定义的行为。)
答案 3 :(得分:2)
您必须malloc
和free
相同的事情!
您是malloc
和realloc
数组,因此您必须释放数组。
你释放了各个顶点。
答案 4 :(得分: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);
}