Linux中简单的Delphi程序中的分段错误-Windows很好
我有这个简单的程序,用 Delphi 10.2 编写,在 Windows 上运行良好,但在 Linux 上崩溃。
本质是所使用的类具有要在其析构函数中执行的代码。
type
Kwak = class
public
index: integer;
constructor Create(index:integer);
destructor Free;
end;
constructor Kwak.Create(index:integer);
begin
self.index := index;
writeln('Welcome Kwak '+inttostr(index));
end;
destructor Kwak.Free;
begin
writeln('Bye Kwak '+inttostr(index));
end;
如果我在调用过程中使用它,就像这样:
procedure myProc1;
var
myKwak:Kwak;
begin
myKwak := Kwak.Create(15);
myKwak.Free;
end;
这在 Windows 上运行良好,但在 Linux 上myKwak离开范围时会导致分段错误(在end中遇到myProc1)。
我想这一切都与 Linux 编译器上的自动引用计数有关。
如果我使用FreeAndNil(),程序不会崩溃,但也不会调用析构函数。
什么是优雅的解决方案?
Free我的程序中有很多这样的。当然,将Free代码转移到其他地方是可能的,但我希望它更优雅。- 程序需要在 Windows 中编译回 XE2,在 10.2 上的 Linux 上。我读到 10.3 遗漏了 ARC,这可能会解决问题,但 10.3 的成本很高。
- 需要的程序更改和
{$IFDEF ...}指令最好最小化。
请告诉我你的建议。
回答
destructor Free; // <-- WRONG!
这是错误的。正确的析构函数被调用Destroy(),它virtual在,TObject所以你需要override在派生类中使用它:
type
Kwak = class
public
index: integer;
constructor Create(index:integer);
destructor Destroy; override;
end;
constructor Kwak.Create(index:integer);
begin
inherited Create;
self.index := index;
writeln('Welcome Kwak '+inttostr(index));
end;
destructor Kwak.Destroy;
begin
writeln('Bye Kwak '+inttostr(index));
inherited;
end;
在非 ARC 系统上,TObject.Free()是一个非虚拟实例方法,Destroy()如果Self不是,则调用析构函数nil。
在ARC系统,编译器默默地替换所有来电Free()与nil分配,递减对象的引用计数。因此,相同的代码可以在 ARC 和非 ARC 系统上以相似的语义使用。对象的Destroy()析构函数在其引用计数下降到 0 时被调用。