在C中查找内存泄漏

时间:2012-08-15 04:00:55

标签: c memory-management

我正试图在下面的代码中找到内存泄漏。 valgrind给了我这个:

==14160== 1,850 (592 direct, 1,258 indirect) bytes in 9 blocks are definitely lost in loss    record 2 of 5
==14160==    at 0x4904A06: malloc (vg_replace_malloc.c:149)
==14160==    by 0x405B1F: tsCreate (ticket_set.c:55)
==14160==    by 0x401ECA: test1TS (main.c:62)
==14160==    by 0x40557C: main (main.c:424)

这是函数:

TicketSetStatus tsCreate(TicketSet* t, int n, int c) {
    if(t==NULL){
        return TS_CANNOT_CREATE;
    }
    if (n <= 0){
        return TS_ILLEGAL_PARAMETER;
    }

    t->usedTravels = 0;
    t->originalTravels = n;
    t->cost = c;
    t->moneyLeft = n * c;
    //Date time is array of travels:
    t->dates =  malloc(sizeof(DateTime *)* (n)); //todo maybe c99 allows dynamic arrays?
    for (int i = 0; i < n; i++) {
        t->dates[i] =  malloc(sizeof(char)*GOOD_LENGTH+1);
        if (t->dates[i] == NULL) {
            free(   t->dates);

            return TS_CANNOT_CREATE;
        }
    }

    return TS_SUCCESS;
}

TicketSetStatus tsDestroy(TicketSet* t, int* moneyLeft) {
    if (t == NULL) {
        return TS_FAIL;
    }
    *moneyLeft = (t->cost) * (t->originalTravels-t->usedTravels);

     for (int i = 0; i < t->originalTravels; i++){
        free(t->dates[i]);
    }
    free(t->dates);

    t=NULL; 
    return TS_SUCCESS;
}

结构为:

struct TS_element {
    int usedTravels;
    int originalTravels;
    int cost;
    DateTime* dates;
    int moneyLeft;
};

typedef char* DateType

实际上玩免费会使程序更频繁地崩溃,所以只要程序正常运行,我就倾向于使用内存泄漏。

2 个答案:

答案 0 :(得分:1)

你是如何使用这个DateTime数组的?如果您稍后踩踏这些值,您将会泄漏。也许是关于字符串赋值的混淆?

char someDateValue[] = "2012-08-15";
t->dates[0] = someDateValue;         // Leak -- your allocated string is lost

相反:

strcpy( t->dates[0], someDateValue );

tsCreate中的错误情况确实存在泄漏:

for (int i = 0; i < n; i++) {
    t->dates[i] =  malloc(sizeof(char)*GOOD_LENGTH+1);
    if (t->dates[i] == NULL) {
        free(t->dates);              // Leak -- every element up to i-1 is lost
        return TS_CANNOT_CREATE;
    }
}

在您完成tsDestroy初始化的数据后,您是否在调用tsCreate?也许你是在没有清理的情况下从main回来的。

如果这些都没有帮助,您应该发布其他代码来说明您如何使用数据结构。

答案 1 :(得分:1)

对于至少一个错误,您可以只关注

...
t->dates =  malloc(sizeof(DateTime*) * (n));    /* first malloc */
for (int i = 0; i < n; i++) {   /* call this loop 1 */
    t->dates[i] =  malloc(sizeof(char)*GOOD_LENGTH+1);  /* second malloc */
    if (t->dates[i] == NULL) {  /* test for malloc error */
        free(   t->dates);      /* free the base array/list */

        return TS_CANNOT_CREATE; /* exit function */
    }
}
...

问题是如果第二个malloc失败,free只释放基(第一个)malloc。它释放第二个malloc创建的任何其他内存分配 在循环1中,在前一循环1迭代上。即如果t->dates[i] = malloc(...在i等于5时失败,则在退出函数之前,不会释放在迭代0到4中分配的内存块。

希望这是有道理的。

更新 @paddy在注明t->dates[0] = someDateValue的错误时是正确的 在这种情况下,所说的是:

char someDateValue[] = "2012-08-15"; 
在这种情况下,

也可以写为

char *someDateValue = "2012-08-15";

这样

t->dates[0] = someDateValue;

只需指定字符串的指针,将指针替换为前面malloc中新分配的块。

参考:如果您仍然感到困惑,可以阅读C FAQ问题6.3 So what is meant by the ``equivalence of pointers and arrays'' in C?以及C FAQ的其余部分。

建议str[n]cpy(或类似replacements)将数组内容(而非其指针)复制到新分配的内存块是正确的。