C 通过链表的迭代导致分段错误

C 通过链表的迭代导致分段错误,c,list,C,List,我只是写了一个简单的链表,但是当通过程序seg faults通过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) {

我只是写了一个简单的链表,但是当通过程序seg faults通过
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;
}
#包括
#包括
typedef结构条目{
无效*值;
结构条目*下一步;
}入境;
类型定义结构列表{
条目*项目;
}名单;
列表*创建(无效){
列表*l;
l=malloc(sizeof(list));
l->items=malloc(sizeof(条目*);
l->items->next=NULL;
返回l;
}
无效添加(列表*l,无效*值){
条目*临时、*上次、*新;
对于(temp=l->items;temp!=NULL;temp=temp->next){
最后=温度;
}
新=malloc(sizeof(*新));
新建->值=值;
新建->下一步=空;
last->next=新建;
}
无效显示(列表*l){
输入*温度;
对于(temp=l->items;temp!=NULL;temp=temp->next){
printf(“%s\n”,临时->值);
}
}
内部主(空){
list*l=create();
添加(l,“第1项”);
添加(l,“第2项”);
添加(l,“第3项”);
添加(l,“第4项”);
显示器(l);
返回0;
}

我已经在一些机器上测试了代码,它在一些机器上运行,在其他机器上不运行。我对错误的来源一无所知。

这没有分配足够的空间:

l->items = malloc(sizeof(entry*));
它应该是
sizeof(entry)
,或者如果您想遵循在其他地方使用的模式:

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

因此,您当前正在占用内存。

FatalError已经发现问题并发布了解决方案。我想补充一点,比问这样一个特定的问题更好的方法是调试代码

valgrind
是一个允许调试内存管理的Linux工具。您所需要做的就是在应用程序中运行该工具,并查看其输出中的错误

如果使用“/myapp”运行应用程序,则只需运行:

# valgrind -v --leak-check=full --show-reachable=yes ./myapp

除了FatalError提到的传递给
malloc
的错误大小之外,您还为
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);
    }
}

在循环的第一次迭代中,这很容易导致segfault,即使分配大小不足以前没有导致segfault。

为了证明您不需要列表结构,因为它只携带一个“head”指针(我将原始条目重命名为llist,end删除了列表和typedefs):

#包括
#包括
结构主义者{
字符*值;
struct-llist*next;
};
void add(结构列表**ll,void*值){
/*找到列表的末尾;
**保留指向(最终NULL)指针的指针。
**如果调用此函数时第一个参数指向
**空指针(空列表),
**此循环将迭代零次。
*/
对于(;*ll!=NULL;ll=&(*ll)->next){;}
*ll=malloc(sizeof(**ll));
(*ll)->值=值;
(*ll)->next=NULL;
}
无效显示(结构列表*l){
对于(;l!=NULL;l=l->next){
printf(“%s\n”,l->value);
}
}
内部主(空){
struct-llist*l=NULL;
添加(&l,“项目1”);
添加(&l,“项目2”);
添加(&l,“第3项”);
添加(&l,“第4项”);
显示器(l);
返回0;
}

1)在调试器中运行它,并告诉我们它在哪里出错;2) 你从不检查malloc的返回值,所以我觉得“在某些机器上,我在其他机器上有足够的内存,我不”总是检查函数调用的失败条件,这些函数调用总是会失败是的,你也是不,你不是特别的只需执行
l->items=malloc(sizeof(entry*));l->items->next=NULL分配指针并将其指定给指向的位置。我首先想到的是使用更好的编译器。这不仅有助于确定此错误,而且有助于确定未来的错误。如果我在gcc中编译这段代码,没有详细的错误标志,我会得到24个错误。这只是伪代码,我知道malloc可能会失败。但是,有足够的内存。分段错误是通过迭代列表(对于
循环的每个
)发生的,正如该线程的标题所述。这与malloc失败无关。它是关于malloc()将指针指向对象,并将其视为对象。顺便说一句:在设计中不需要结构列表,只会让人困惑。+1,
valgrind
非常棒,很快就会发现。谢谢,非常感谢。
#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;
}