链表中的分段错误

时间:2012-01-12 22:24:28

标签: c pointers linked-list segmentation-fault

编辑:Dijkstra的答案是解决这个问题的方法。我的列表未初始化为NULL

我正在处理链接列表以存储唯一的单词列表,当我尝试遍历列表时会出现段错误。 Gdb给了我:

    Program received signal SIGSEGV, 
    Segmentation fault. 0x0000003a07e47ff7 in vfprintf () from /lib64/libc.so.6 
    Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.7.el6_0.5.x86_64

列表的插入代码是:

typedef struct L { char x[40] ; int occ; struct L *next ;} List;
List *insertList( char *in, List *l )
{
    List *t = calloc( 1, sizeof( List ) ) ;
    strcpy(t->x, in);
    t->occ = 1;
    t->next = l ;
    return t ;
}

void printList(List *l)
{
    List *l2 = l;
    while(l2)
    {
        printf("%s ", l2->x);
        l2 = l2->next;
    }
    return;
}

循环显示单词,将它们插入到链表中,看似很好。当我遍历列表以显示单词(大约4200个单词)时,大约98%的ish将显示正常,然后它会在没有警告的情况下进行分段。

通过更多的检查,它会以与它们相加的相反顺序(这是有意义的)读回单词,并且在分割之前将达到列表末尾的第5个单词(添加的第5个单词)。我已经尝试调整插入函数以允许超过40个字符串的字符串,但是在开头插入的字段(并且是segfaulted)都在20个字符以下。

如果我更多地挖掘,如果我在printList函数中printf l2-> next-> next-> next-> next,那么插入的第一个单词就在那里。

有人可能会指出我正确的方向吗?

由于

4 个答案:

答案 0 :(得分:3)

gdb(如果你不使用linux,则是另一个调试器)是我追踪段错误的首选工具。使用调试符号编译代码并在调试器中运行它。当您崩溃时,检查导致崩溃的线路。根据需要使用backtrace命令。按照这些步骤,我总是告诉我如何修复段错误。

答案 1 :(得分:2)

我最好的猜测是strncpy而不是strcpy可以解决你的问题,听起来有些东西在列表的后面某处覆盖了你的'next'指针,而'in'中的字符串太长了肯定会这样做。

不要忘记strncpy不会终止太长的字符串,所以要确保放置

x[39]=0;

确保字符串正确终止。

答案 2 :(得分:2)

您是如何初始化第一个节点的?

你说“前几个字导致了seg故障”,但是中断可能会阻止他们打印,问题实际上是在最后。

我的假设(而且它只是一个猜测:P)是你的第一个节点没有next = NULL;,它只是未初始化的内存。因此,while循环不会检测到它到达列表的末尾并尝试打印奇怪的东西,从而导致段错误。

答案 3 :(得分:2)

这是一种风格的评论(不被SO人们所赏识; - [) plain for循环有什么问题?为什么在这种情况下有一个有效的惯用结构时,你会在循环内部进行迭代?

void printList(List *lp)
{
    List *l2;

    for(l2=lp; l2; l2 = l2->next)
    {
        printf("%s ", l2->x);
    }
    return;
}