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

この配列をどのように使用しています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片付けもせずに帰ってきたのかもしれません。

これが役に立たない場合は、追加のコードを投稿して、データ構造をどのように使用しているかを示す必要があります。

于 2012-08-15T04:16:16.780 に答える
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 */
    }
}
...

問題は、2 番目mallocが失敗した場合、freeベース (最初) の malloc のみが解放されることです。前のループ 1 の繰り返しで、ループ 1 の 2 番目の malloc によって作成された他のメモリ割り当ては解放されません。つまり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を読んでください。では、C における「ポインタと配列の同等性」とはどういう意味ですか? C FAQ の残りの部分と同様に。

また、str[n]cpy (または同様の置換) を使用して、配列の内容(ポインターではなく) を新しく割り当てられたメモリ ブロックにコピーすることをお勧めします。

于 2012-08-15T04:25:18.940 に答える