即使在指向struct的指针之后,C内存也会泄漏

时间:2016-03-06 17:25:17

标签: c pointers struct memory-leaks

我有二次多项式系数的结构。我声明了这个结构类型的变量,我读取了系数的值,然后我创建并初始化了一个指向这个结构的指针。然后我使用我的struct和指向struct变量的指针显示系数的值。最后,我将指向struct的指针设置为NULL并释放它。

然而,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;
}

2 个答案:

答案 0 :(得分:2)

内存泄漏1

第一个问题在于以下语句,它与代码的作用不一致:

  

然后我创建并初始化一个指向这个结构的指针

请记住,变量pCoeff指针,即它存储地址

在第

  

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

您存储在pCoeff新动态分配结构的地址中。接下来,在行

  

pCoeff = &coeff;

您在pCoeff(覆盖之前的值)中存储静态分配的结构coeff地址。这样做会丢失对动态分配的内存的唯一引用,从而导致内存泄漏。

实际复制结构的的正确解决方案是使用memcpy函数,或

*pCoeff = coeff;

内存泄漏2

第二个问题在于解除分配期间的陈述顺序。

在第

pCoeff = NULL; 

您存储在pCoeff(覆盖之前的值)NULL 地址。这样做,您将再次失去唯一的引用并导致内存泄漏。

然后,在行

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);

...

答案 1 :(得分: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结构,或使用堆栈上的那个。你不需要同时做这两件事。