1

これは私を夢中にさせています。この二重リンクリストでテストプログラムを実行すると、リストを解放しようとするとセグメンテーション違反が発生します。割り当てられたメモリを正しく解放しないためにメモリリークが発生することはわかっていますが、何を試しても修正されないようです。メモリリークとセグメンテーション違反を回避するためにメモリを解放する必要がある場所に関するヘルプをいただければ幸いです。

struct list { 

    char *value;
    struct list *next;
    struct list *prev;
};

const char *list_node_value(list_t *node) {

    return node->value;
}

list_t *list_first(list_t *list) {

    return list;
}

list_t *list_last(list_t *list) {

    return list->prev;
}

list_t *list_next(list_t *node) {

    return node->next;
}

list_t *list_previous(list_t *node) {

    return node->prev;

}

static void failed_allocation(void) {

    fprintf(stderr, "Out of memory.\n");
    abort();
}

static list_t *new_node(const char *value) {

    list_t *node = malloc(sizeof(list_t));
    if (!node) failed_allocation();
    node->value = malloc(strlen(value));
    if (!node->value) failed_allocation();
    strcpy(node->value, value);
    return node;
}

list_t *list_insert_before(list_t *list, list_t *node, const char *value) {

    list_t *insert_node = new_node(value);
    insert_node->prev = node->prev;
    insert_node->next = node;
    insert_node->next->prev = insert_node;
    insert_node->prev->next = insert_node;
    if (list == node) {
        return insert_node;
    } else {
        return list;
    }
}

list_t *list_append(list_t *list, const char *value) {

    if (list) {

        (void) list_insert_before(list, list, value);
        return list;
    } else {

        list_t *node = new_node(value);
        node->prev = node->next = node;
        return node;
    }
}

list_t *list_prepend(list_t *list, const char *value) {

    if (list) {

        return list_insert_before(list, list, value);
    } else {

        list_t *node = new_node(value);
        node->prev = node->next = node;
        return node;
    }
}

list_t *list_remove(list_t *list, list_t *node) {

    (node->prev)->next = node->next;
    (node->next)->prev = node->prev;
    if (list != node) {

    return list;
    } else {

        return list->next == list ? NULL : list->next;
    }   
}

void list_free(list_t *list) {

    while (list_remove(list, list_last(list)) != NULL) { }

    }



void list_foreach(list_t *list, void (*function)(const char*)) {

    if (list) {

        list_t *cur = list_first(list);
        do {

            function(cur->value);
            cur = cur->next;
        } while (cur != list_first(list));
    }
}
4

5 に答える 5

1

あなたの問題はヒープの破損です。あなたが持っている:

   node->value = malloc(strlen(value));

そのはず:

   node->value = malloc(strlen(value)+1);
于 2012-09-22T18:09:38.263 に答える
1
  1. あなたは何も解放していません。リストから切断しても解放されません。

  2. これは、二重にリンクされたリストだけではありません。循環リストです。

  3. リストを初期化するコードが表示されません。これが問題の原因である可能性があります。

于 2012-09-22T18:11:01.983 に答える
0

efenceまたはvalgrindにリンクされたプログラムを実行します。

これにより、メモリが失われた場所やポインタが逆参照された場所などがわかります。

于 2012-09-22T18:07:34.793 に答える
0
if (!node) failed_allocation();
node->value = malloc(strlen(value));

'\0'問題は、 NULバイトにスペースを割り当てなかったことです。試す:

if (!node) failed_allocation();
node->value = malloc(strlen(value)+1);
于 2012-09-22T18:09:53.513 に答える
0

ここに少なくとも1つの欠陥があります:

node->value = malloc(strlen(value));

strlen(value) + 1ターミネータ文字をゼロに保つ必要があります。そうしないと、次の呼び出しstrcpy()でバッファオーバーランが発生し、ヒープが損傷する可能性があります。

node->value = malloc(strlen(value) + 1);
于 2012-09-22T18:10:17.827 に答える