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

Он не печатает «свободную память», так где же он свободен? вот что 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 

В чем проблема с кодом? Должен ли я присвоить имя вершины по-другому? Спасибо за помощь!

EDIT: Спасибо всем! Я исправил код, теперь я не освободив отдельных элементов, т.е.

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

и, конечно, вновь установив I 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.

+2

Это правда - но фиксация, что сломается таНос плохо - как программа будет освободив вещи, которые не были malloced. –

4

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

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

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

+2

Ответ Фрэнсиса правильный, но это вторая ошибка, скрывающаяся. –

2

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

(Fun часть:. Так как arr+0 равно arr, как только вы переинициализации i правильно, как указано в Francis's answer, первая итерация цикла освобождает весь массив С тех пор, вы не итерация массива больше, что нет существует, что само по себе является неопределенным поведением.)

2

У вас должно быть malloc и free такие же вещи!

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

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 Это хороший момент! Мне нравится, что он «должен быть выброшен»! :) –

 Смежные вопросы

  • Нет связанных вопросов^_^