编辑: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% 的单词将显示正常,然后它会在没有警告的情况下出现段错误。
再进行一些检查,它会以与添加单词相反的顺序读回单词(这是有道理的(,并且在段错误之前将到达列表末尾的第 5 个单词(添加的第 5 个单词(。我尝试调整插入功能以允许超过 40 个字符长的字符串,但是在开头插入(并且被段错误(的单词都低于 20 个字符。
通过更多的挖掘,如果我在printList函数中printf l2->next->next->next->next-next,则插入的第一个单词就在那里。
谁能用这个为我指出正确的方向?
谢谢
gdb(如果你不使用Linux,或者另一个调试器(是我跟踪段错误的选择工具。使用调试符号编译代码并在调试器中运行它。崩溃时,请检查导致崩溃的线路。根据需要使用回溯命令。遵循这些步骤几乎总是向我展示如何修复段错误。
我最好的猜测是 strncpy 而不是 strcpy 可以解决您的问题,听起来好像有什么东西覆盖了列表后期的某个地方的"下一个"指针,而"in"中太长的字符串肯定会做到这一点。
不要忘记 strncpy 不会终止太长的字符串,所以要确保将
x[39]=0;
以确保字符串将正确终止。
你如何初始化你的第一个节点?
你说"前几个词导致了赛格错误",但中断可能会阻止他们打印,问题实际上就在最后。
我的假设(实际上只是一个猜测:P(是你的第一个节点没有next = NULL;
,它只是未初始化的内存。因此,while 循环不会检测到它已到达列表的末尾,并尝试打印一些奇怪的内容,从而导致段错误。
这是一个文体评论(SO的人不会欣赏;-[ (普通的 for 循环有什么问题?当这种事情有一个有效的习惯构造时,为什么要在循环内迭代?
void printList(List *lp)
{
List *l2;
for(l2=lp; l2; l2 = l2->next)
{
printf("%s ", l2->x);
}
return;
}