malloc char * внутри функции, valgrind сообщает об утечке памяти - PullRequest
1 голос
/ 24 декабря 2011

Я довольно новичок в 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", так где это было free'd?Вот что Вальгринд сказал об этом:

==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. Не могу поверить, что я упустил это из виду.Большое спасибо!

Ответы [ 5 ]

5 голосов
/ 24 декабря 2011

Вы не сбрасываете 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.

4 голосов
/ 24 декабря 2011

Реаллок здесь не имеет значения. Вы делаете это:

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

Вы не должны освобождать отдельные элементы массива.

2 голосов
/ 24 декабря 2011

Проблема может быть из-за кода ниже, где 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);
}
2 голосов
/ 24 декабря 2011

Вы должны malloc и free одно и то же!

Вы malloc и realloc используете массив, поэтому вы должны освободить массив. Вы освобождаете отдельные вершины.

2 голосов
/ 24 декабря 2011

Вы не можете free ни один указатель, кроме того же, который вы получили от malloc, realloc и т. Д. Это неопределенное поведение, и вы запрашиваете повреждение кучи или хуже, если вы это сделаете.

(Интересная часть: поскольку arr+0 равно arr, после правильного повторного ввода i, как указано в ответе Фрэнсиса , первая итерация цикла освобождает всемассив. С этого момента вы перебираете массив, которого больше не существует, что само по себе является неопределенным поведением.)

...