0

単純なリンクリストを作成しましたが、を介してリストを反復処理するadd()display()、プログラムのセグメンテーション違反が発生します。

#include <stdlib.h>
#include <stdio.h>

typedef struct entry {
    void *value;
    struct entry *next;
} entry;

typedef struct list {
    entry *items;
} list;

list *create(void) {
    list *l;

    l = malloc (sizeof(list));
    l->items = malloc(sizeof(entry*));
    l->items->next = NULL;

    return l;
}

void add(list *l, void *value) {
    entry *temp, *last, *new;

    for (temp = l->items; temp != NULL; temp = temp->next) {
        last = temp;
    }

    new = malloc(sizeof(*new));

    new->value = value;
    new->next = NULL;

    last->next = new;
}

void display(list *l) {
    entry *temp;

    for (temp = l->items; temp != NULL; temp = temp->next) {
        printf("%s\n", temp->value);
    }
}

int main(void) {
    list *l = create();

    add(l, "item1");
    add(l, "item2");
    add(l, "item3");
    add(l, "item4");

    display(l);

    return 0;
}

私はいくつかのマシンでコードをテストしましたが、それはいくつかのマシンで動作し、他のマシンでは動作しません。エラーの原因についてはわかりません。

4

4 に答える 4

6

これでは十分なスペースが割り当てられません。

l->items = malloc(sizeof(entry*));

それはsizeof(entry)、または他の場所で使用するパターンに従いたい場合は、次のようになります。

l->items = malloc(sizeof(*l->items));

その結果、あなたは現在、記憶を踏みにじっています。

于 2012-06-04T19:44:01.993 に答える
3

malloc上記のFatalErrorに渡された間違ったサイズに加えて、次のメモリを割り当てますl->items

list *create(void) {
    list *l;

    l = malloc (sizeof(list));
    l->items = malloc(sizeof(entry*));
    l->items->next = NULL;

    return l;
}

ただし、何も設定しないでください。これl->items->valueは初期化されていないポインタであり、印刷時に逆参照しようとすると

void display(list *l) {
    entry *temp;

    for (temp = l->items; temp != NULL; temp = temp->next) {
        printf("%s\n", temp->value);
    }
}

ループの最初の反復では、割り当てサイズが不十分なために以前はセグメンテーション違反が発生していなかったとしても、セグメンテーション違反が発生する可能性があります。

于 2012-06-04T19:52:52.713 に答える
2

FatalErrorはすでに問題を発見し、解決策を公開しています。そのような特定の質問をするよりも良いアプローチは、コードをデバッグすることであることを付け加えたいと思います。

valgrindは、メモリ管理のデバッグを可能にするLinuxツールです。あなたがする必要があるのは、あなたのアプリケーションでツールを実行し、エラーがないかその出力を調べることです。

「./myapp」を使用してアプリケーションを実行する場合は、次を実行する必要があります。

# valgrind -v --leak-check=full --show-reachable=yes ./myapp
于 2012-06-04T19:51:24.960 に答える
0

リスト構造が必要ないことを証明するために、リスト構造には「ヘッド」ポインタしか含まれていないため(元のエントリの名前をllistに変更し、リストとtypedefを削除しました)。

#include <stdlib.h>
#include <stdio.h>

struct llist {
    char *value;
    struct llist *next;
};

void add(struct llist **ll, void *value) {

      /* find the end of the list;
      ** keeping a pointer to the (final NULL) pointer.
      ** If this function is called with the first argument pointing to
      ** a NULL pointer (the empty list),
      ** this loop will iterate zero times.
      */
    for ( ; *ll != NULL; ll = &(*ll)->next) {;}

    *ll = malloc(sizeof(**ll));

    (*ll)->value = value;
    (*ll)->next = NULL;

}

void display(struct llist *l) {

    for (; l != NULL; l = l->next) {
        printf("%s\n", l->value);
    }
}

int main(void) {
    struct llist *l = NULL;

    add(&l, "item1");
    add(&l, "item2");
    add(&l, "item3");
    add(&l, "item4");

    display(l);

    return 0;
}
于 2012-06-04T20:05:45.000 に答える