链表插入元素触发SIGSEGV异常 求问题排查指引
解决Pascal链表尾部插入时的SIGSEGV异常问题
你遇到的External: SIGSEGV错误本质是空指针解引用,核心问题出在你的CreateList过程没有正确维护链表的尾指针RefEnd,具体原因如下:
- 原
CreateList采用头插法构建链表,但只更新了头指针outRefBeginning,完全没有对尾指针RefEnd做任何更新操作。 - 主程序中你初始化
RefEnd := RefBeginning(也就是nil),之后CreateList运行全程都没修改过RefEnd,所以当你调用InsertElement时,传入的outRefEnd仍然是nil。 - 此时因为链表已经有元素,
InsertElement会进入else分支,执行outRefEnd^.next := RefNew——这相当于对空指针进行解引用,直接触发段错误。
修正方案
我们需要让CreateList过程同时维护头指针和尾指针,改用尾插法构建链表(天然适合维护尾指针),同时清理不必要的全局变量:
具体修改点
- 移除全局的
Pointer变量,改用局部变量避免全局状态带来的意外问题 - 重写
CreateList过程,添加尾指针参数,用尾插法构建链表,同步更新头、尾指针 - 主程序中正确初始化并传递
RefEnd参数给CreateList
修正后的完整代码
program InserElement(input, output); {让用户输入整数构建链表,随后在链表尾部插入元素并打印包含新元素的链表} {$mode objfpc}{$H+} uses {$IFDEF UNIX}{$IFDEF UseCThreads} cthreads, {$ENDIF}{$ENDIF} Classes; type tRefList = ^tList; tList = record info : integer; next : tRefList end; var RefBeginning: tRefList; RefEnd : tRefList; Number : integer; procedure CreateList(var outRefBeginning: tRefList; var OutRefEnd: tRefList); {通过用户输入创建线性链表} var RefNew : tRefList; begin writeln('请输入自然数,输入0结束输入。'); readln(Number); while Number <> 0 do begin new (RefNew); RefNew^.info := Number; RefNew^.next := nil; if outRefBeginning = nil then begin outRefBeginning := RefNew; OutRefEnd := RefNew; end else begin outRefEnd^.next := RefNew; OutRefEnd := RefNew end; readln (Number) end; { while-loop } end; {CreateList} procedure InsertElement(inNumber : integer; var outRefBeginning : tRefList; var outRefEnd : tRefList); {在链表尾部插入新元素。outRefBeginning指向链表首元素,outRefEnd指向链表尾元素,inNumber赋值给新元素的info字段} var RefNew : tRefList; begin {创建并初始化新元素} new(RefNew); RefNew^.info := inNumber; RefNew^.next := nil; {在线性链表尾部插入元素} if outRefBeginning = nil then begin outRefBeginning := RefNew; outRefEnd := RefNew end else begin outRefEnd^.next := RefNew; outRefEnd := RefNew; end; end;{ InsertElement } procedure PrintList; {打印链表所有元素} var RefNew : tRefList; begin RefNew := RefBeginning; while RefNew <> nil do begin writeln (RefNew^.info); RefNew := RefNew^.next end; end; begin RefBeginning := nil; RefEnd := nil; CreateList(RefBeginning, RefEnd); InsertElement(5,RefBeginning,RefEnd); PrintList; readln; end.
这样修改后,CreateList会正确维护尾指针RefEnd,调用InsertElement时outRefEnd指向的是链表的最后一个节点,就能安全地执行outRefEnd^.next := RefNew操作了。
内容的提问来源于stack exchange,提问作者Lucky
相关产品推荐
相关产品推荐

