Lazarus创建动态数组时触发SIGSEGV错误,寻求解决办法
解决动态数组触发SIGSEGV的问题
嘿,我来帮你搞定这个段错误的问题!你遇到的SIGSEGV十有八九是动态数组的初始化或访问逻辑出错导致的,和32/64位Lazarus版本关系不大——毕竟不管是32还是64位,Pascal动态数组的基础规则都是一致的。
先说说常见的坑点
你提到要把唯一城市存入动态数组,那大概率是以下几个环节出了问题:
- 动态数组默认是
nil状态,直接赋值或访问索引会直接触发段错误,必须先初始化; - 添加元素时没正确扩展数组长度,导致越界访问;
- 去重循环时索引范围写错,超出了数组的实际长度。
给你一个正确的实现示例
我结合你的需求写了一段标准代码,你可以对照着修改自己的程序:
unit Unit1; {$mode objfpc}{$H+} interface uses Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls; type { TForm1 } TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private Cities: array of string; // 动态数组存储唯一城市 public end; var Form1: TForm1; implementation {$R *.lfm} { TForm1 } procedure TForm1.Button1Click(Sender: TObject); var SL: TStringList; I, J: Integer; City: string; IsDuplicate: Boolean; begin SL := TStringList.Create; try SL.LoadFromFile('temekek.txt'); SetLength(Cities, 0); // 先初始化动态数组为空 for I := 0 to SL.Count - 1 do begin // 跳过空行,避免无效处理 if Trim(SL[I]) = '' then Continue; // 分割行内容,取第一个字符串(城市名) // TStringList默认用空格分隔,正好匹配你的「字符串 字符串 整数」格式 City := Trim(SL.Names[I]); // 检查是否已存在该城市 IsDuplicate := False; for J := 0 to Length(Cities) - 1 do begin if Cities[J] = City then begin IsDuplicate := True; Break; end; end; // 如果是新城市,添加到动态数组 if not IsDuplicate then begin SetLength(Cities, Length(Cities) + 1); // 扩展数组长度 Cities[Length(Cities) - 1] := City; // 赋值到新的索引位(数组从0开始) end; end; // 输出统计结果验证 ShowMessage('唯一城市数量:' + IntToStr(Length(Cities))); finally SL.Free; // 务必释放资源 end; end; end.
你可以排查自己代码的这几个地方
- 动态数组初始化:你是不是直接就往数组里赋值了?比如没写
SetLength(Cities, 0)就直接用Cities[0] := ...?这会直接触发段错误,因为此时数组还没有分配内存。 - 数组扩展逻辑:添加元素时是不是没调用
SetLength就直接访问新索引?比如想添加第2个元素时,数组长度还是1,直接写Cities[1] := ...就会越界。 - 循环索引范围:去重循环时,是不是把
J的上限写成了Length(Cities)而不是Length(Cities)-1?因为数组索引是从0开始的,Length(Cities)是元素总数,最大索引是总数减1。
额外的调试小技巧
用Lazarus自带的调试器,在触发错误的那一行设个断点,查看动态数组的Length值——比如在赋值前看看数组当前长度是多少,是不是和你预期的一致,这样很容易定位到问题所在。
内容的提问来源于stack exchange,提问作者vaso123
相关产品推荐
相关产品推荐

