编辑: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,那么插入的第一个单词就在那里。
有人可能会指出我正确的方向吗?
由于
答案 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;
}