1

リンクリストと述語を受け取り、この条件を満たすリンクリストのすべての値を含む配列を返す関数をCで記述しています。関数は次のとおりです。

void **get_all_that(list_t *l, int (*pred)(const void *)) {
    void **vals = NULL;
    int i = 0; // Number of matches found
    const size_t vps = sizeof(void *);
    node_t *n = l->first;
    while (n) {
        if (pred(n->value)) {
            vals = (void **)realloc(vals, i*vps); // (*)
            vals[i] = n->value;
            i++;
        }
        n = n->next;
    }
    if (vals != NULL) {
        vals = (void **)realloc(vals, i*vps);
        vals[i] = NULL; // NULL-terminate array
    }
    return vals;
}

常に1を返す述語(つまり、get_all_thatは基本的にto_array)を渡しましたが、i=4の反復でスター付きの行でエラーが発生します。バックトレース(SIGABRTから自動的に出力された)のエラーは、「*** glibcが検出されました***〜/ list / test:realloc():invalid next size:0x0804c0e8***」です。

GDBを開いて、i=4のときにreallocを呼び出す直前に中断するように指示しました。次に、GDBから手動でrealloc(vals、i * vps)を呼び出そうとすると、次のエラーメッセージが表示されました。

誰が何が起こっているのか知っていますか?

4

2 に答える 2

2

割り当てreallocている要素が少なすぎます。に置き換えiてみてくださいi+1reallocまた、渡したポインタを置き換える前に、の失敗をチェックする必要があります。そうしないと、失敗時にメモリリークが発生し(チェックに失敗したためにクラッシュすることは言うまでもありませんNULL)、戻り値から不要で醜いキャストを削除します。のreallocもいいでしょう。

于 2010-10-05T03:11:23.217 に答える
0

そして、最初reallocに長さを0で呼び出します。これはfreeです。したがって、置くべきアドバイスi+1は二重に重要です。

于 2010-10-05T05:47:50.403 に答える