0

我试图在以下代码中找到内存泄漏。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

实际上玩免费的程序经常会导致程序崩溃,所以只要程序正常运行,我倾向于忍受内存泄漏。

4

2 回答 2

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。它不会释放循环 1 中的第二个 malloc 在前一个循环 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

Ref: 如果您仍然感到困惑,您可以阅读C 常见问题解答问题 6.3那么 C 中的“指针和数组等价”是什么意思?以及 C FAQ 的其余部分。

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

于 2012-08-15T04:25:18.940 回答
1

你是如何使用这个数组的DateTime?如果您稍后踩踏这些值,您将得到泄漏。也许对字符串分配感到困惑? IE

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没有清理就回来了。

如果这些都没有帮助,您应该发布额外的代码来展示您如何使用您的数据结构。

于 2012-08-15T04:16:16.780 回答