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,end 删除了列表和 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 回答