简体   繁体   English

函数内的malloc char *,valgrind报告内存泄漏

[英]malloc char* inside a function, valgrind reports memory leak

I am pretty new to C, and am doing toy programs to learn it. 我对C很陌生,并且正在做玩具程序来学习它。 The following code compiles, outputs correctly, but Valgrind reports a memory leak: 以下代码可以正确编译,输出,但是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;
}

The vertex is coded in a header file, 顶点编码在头文件中,

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

The output is: 输出为:

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

It doesn't print "free'd memory", so where was it free'd? 它不会打印“已释放的内存”,那么它在哪里被释放? here is what Valgrind had to say about it: 这是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

What is the problem with the code? 代码有什么问题? Should I allocate the name of the vertex differently? 我应该以不同的方式分配顶点名称吗? Thanks for the help! 谢谢您的帮助!

EDIT: Thanks to all of you! 编辑:谢谢大家! I've fixed the code, now I am not freeing individual elements, ie 我已经修复了代码,现在我不释放单个元素,即

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

and of course re-setting the i to 0. can't believe I overlooked it. 并将i重置为0。不敢相信我忽略了它。 Thanks a lot! 非常感谢!

You are not resetting i in the loop that frees the code. 您不会在释放代码的循环中重置i Those loops should look like this: 这些循环应如下所示:

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

Added another point: 补充一点:

free_vertex() should not have the: free_vertex()不应具有:

free(ver)

line, which is what others are saying. 线,这是别人在说的。

free_vertex() and add_vertex() should be parallel in the sense that free frees only what was allocated in add. free_vertex()和add_vertex()应该平行,即释放仅释放add中分配的内容。

The realloc is irrelevant here. 这里的realloc无关紧要。 You're doing this: 您正在执行此操作:

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

You shouldn't be freeing single elements of the array. 您不应该释放数组的单个元素。

You can't free any pointer other than the exact same one you get back from malloc , realloc , etc. That's undefined behavior, and you're asking for heap corruption or worse if you do it. 除了从mallocrealloc等返回的指针完全相同之外,您不能free任何指针。这是未定义的行为,并且您要求进行堆破坏或更糟。

(Fun part: Since arr+0 is equal to arr , once you reinit i correctly as mentioned in Francis's answer , the first iteration through the loop frees the whole array. From then on, you're iterating over an array that no longer exists, which is undefined behavior in itself.) (有趣的部分:由于arr+0等于arr ,一旦您按照Francis的回答正确地初始化了i ,循环中的第一次迭代将释放整个数组。从那时起,您将遍历一个不再存在的数组,这本身就是未定义的行为。)

You have to malloc and free the same things! 您必须mallocfree相同的东西!

You are malloc and realloc ing an array, so you must free the array. 您正在malloc并重新realloc一个数组,因此必须释放该数组。 You are freeing the individual vertexes. 您正在释放单个顶点。

The problem could be because of the below code where i is not initialized back to zero! 问题可能是由于以下代码未将i初始化回零!

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

So it should be 所以应该

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM