2016-03-06 3 views
-1

У меня есть структура для коэффициентов полиномы второй степени. Я объявляю переменную этого типа структуры, я читаю значения коэффициентов, затем создаю и инициализирую указатель на эту структуру. Затем я показываю значения коэффициентов, используя мою структуру и мой указатель на структурные переменные. Наконец, я установил свой указатель на struct в NULL, и я освобожу его.C утечка памяти даже после освобождения указателя на структуру

Однако, valgrind обнаруживает утечку памяти, и я не могу, для жизни меня, понять, почему. Не могли бы вы помочь мне понять, пожалуйста?

valgrind ./polynome --leak-check=full 
==11046== Memcheck, a memory error detector 
==11046== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al. 
==11046== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info 
==11046== Command: ./polynome --leak-check=full 
==11046== 
2 3 4 
pCoeff: a = 2.000000, b = 3.000000, c = 4.000000 
coeff: a = 2.000000, b = 3.000000, c = 4.000000 
==11046== 
==11046== HEAP SUMMARY: 
==11046==  in use at exit: 24 bytes in 1 blocks 
==11046== total heap usage: 1 allocs, 0 frees, 24 bytes allocated 
==11046== 
==11046== LEAK SUMMARY: 
==11046== definitely lost: 24 bytes in 1 blocks 
==11046== indirectly lost: 0 bytes in 0 blocks 
==11046==  possibly lost: 0 bytes in 0 blocks 
==11046== still reachable: 0 bytes in 0 blocks 
==11046==   suppressed: 0 bytes in 0 blocks 
==11046== Rerun with --leak-check=full to see details of leaked memory 
==11046== 
==11046== For counts of detected and suppressed errors, rerun with: -v 
==11046== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) 

Вот моя C программа:

#include <stdio.h> 
#include <stdlib.h> 

typedef struct { 
    double a; 
    double b; 
    double c; 
} Coefficient; 

int main() { 
    Coefficient *pCoeff = NULL; 
    Coefficient coeff; 

    scanf("%lf %lf %lf", &coeff.a, &coeff.b, &coeff.c); 

    pCoeff = (Coefficient *)malloc(sizeof(Coefficient)); 
    if (pCoeff == NULL) { 
     fprintf(stderr, "Memory allocation error.\n"); 
     exit(1); 
    } 

    pCoeff = &coeff; 

    printf("pCoeff: a = %lf, b = %lf, c = %lf\n", pCoeff->a, pCoeff->b, pCoeff->c); 
    printf(" coeff: a = %lf, b = %lf, c = %lf\n", coeff.a, coeff.b, coeff.c); 

    pCoeff = NULL; 
    free(pCoeff); 

    return 0; 
} 
+3

Вы должны освободить указатель первым. Затем установите значение NULL. –

+0

@MartinZabel: если я не устанавливаю указатель на NULL перед освобождением, я получаю двойную свободную ошибку или ошибку с коррупцией (потому что она все еще указывает на адрес переменной coeff). – user3638629

+0

@ user3121023: да, да, я просто хотел проверить эквивалент 'int var = 3; int * p = &var; 'в динамическом распределении с использованием структур, и я не понимаю, почему у меня утечка памяти. Или вы хотите сказать, что я не должен это делать? – user3638629

ответ

2

Утечка памяти 1

Вы первая проблема заключается в следующем заявлении, которое не соответствует тому, что делает код:

я создать и инициализировать указатель на эту структуру

Помните, что переменная pCoeff является указателем , т.е. хранит адрес .

В строке

pCoeff = (Coefficient *)malloc(sizeof(Coefficient));

хранить в pCoeff в адрес нового динамически выделяемой структуры. Далее, в строке

pCoeff = &coeff;

хранить в pCoeff (перезапись предыдущего значения) адреса в статический выделенной структуре coeff. При этом вы теряете свою единственную ссылку на динамически распределенную память и, следовательно, вызывают утечку памяти.

Правильное решение на самом деле Вы можете скопировать значения от структуры будет либо использовать функцию memcpy или

*pCoeff = coeff; 

Утечка памяти 2

Вторая проблема заключается в том порядке заявлений во время освобождения.

В строке

pCoeff = NULL; 

хранить в pCoeff (перезапись предыдущее значение) Нулевая адрес. Поступая таким образом, вы снова потеряете свою единственную ссылку и вызовите утечку памяти.

Затем в строке

free(pCoeff); 

вы звоните free значением, хранящимся в pCoeff. Поскольку значение теперь NULL, функция ничего не делает.

Правильная последовательность открепления будет иметь два заявления в обратном порядке:

pCoeff = NULL; 
free(pCoeff); 

ненужного код

Переменная coeff кажется излишней, так как вы выделяете тот же тип динамически и скопировать значение , Вы можете выделить сначала, а затем читать непосредственно в память, указанную pCoeff.

Например:

Coefficient *pCoeff = NULL; 
pCoeff = (Coefficient *)malloc(sizeof(Coefficient)); 
if (NULL == pCoeff) { 
    fprintf(stderr, "Memory allocation error.\n"); 
    exit(1); 
} 

scanf("%lf %lf %lf", &pCoeff->a, &pCoeff->b, &pCoeff->c); 
/* TODO: Check the return value of scanf. */ 

printf("pCoeff: a = %lf, b = %lf, c = %lf\n", pCoeff->a, pCoeff->b, pCoeff->c); 

... 
+0

Спасибо. Теперь ясно. Да, 'coeff' избыточен, я просто тестировал структуры в стеке против динамического распределения. – user3638629

1

Ваша проблема заключается в эти строки кода не имеет смысла, вместе взятые:

Coefficient *pCoeff = NULL; 
Coefficient coeff; 

// this points pCoeff at a malloc()'d structure 
pCoeff = (Coefficient *)malloc(sizeof(Coefficient)); 

// this points pCoeff at the structure on the stack - and 
// leaks the one malloc()`d above 
pCoeff = &coeff; 

pCoeff = NULL; 
// free() of a NULL pointer does nothing 
free(pCoeff); 

Либо malloc() затем free() в Coefficient структуру, или используйте тот, который находится в стеке. Вам не нужно делать то и другое.

+0

Да, вы правы, это не имеет смысла. :) Я просто пытался понять подработку наличия структур в стеке против использования динамического выделения. Благодаря вашему ответу и другим, которые я получил, я теперь понимаю. – user3638629

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