Linux 中的 easy Delphi 程序中的分段错误 - Windows 没问题
Segmentation fault in easy Delphi program in Linux - Windows is fine
我有这个简单的程序,用 Delphi 10.2 编写,运行 在 Windows 上运行良好,但在 Linux.
上崩溃
其实质就是使用的class在其析构函数中有要执行的代码
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 上运行良好,但在 myKwak
离开范围时在 Linux 上导致分段错误(在 myProc1
中遇到 end
).
我猜这一切都与 Linux 编译器上的自动引用计数有关。
如果我使用FreeAndNil()
,程序不会崩溃,但也不会调用析构函数。
什么是优雅的解决方案?
- 我的程序中有很多这样的
Free
。当然,将 Free
代码转移到其他地方是可以的,但我希望它更优雅。
- 程序需要在 Windows 中编译回 XE2,在 Linux 10.2。我读到 10.3 省略了 ARC,这可能会解决问题,但 10.3 很昂贵。
- 需要更改程序并且
{$IFDEF ...}
指令最好最小化。
请告诉我你的建议。
destructor Free; // <-- WRONG!
这是错误的。正确的析构函数称为 Destroy()
,它在 TObject
中是 virtual
,因此您需要在派生 类:
中 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()
是一个非虚拟实例方法,如果 Self
不是 nil
,则调用 Destroy()
析构函数。
在 ARC 系统上,编译器会自动将所有对 Free()
的调用替换为 nil
赋值,从而减少对象的引用计数。这样可以在 ARC 和非 ARC 系统上使用具有相似语义的相同代码。对象的 Destroy()
析构函数在其引用计数降至 0 时被调用。
我有这个简单的程序,用 Delphi 10.2 编写,运行 在 Windows 上运行良好,但在 Linux.
上崩溃其实质就是使用的class在其析构函数中有要执行的代码
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 上运行良好,但在 myKwak
离开范围时在 Linux 上导致分段错误(在 myProc1
中遇到 end
).
我猜这一切都与 Linux 编译器上的自动引用计数有关。
如果我使用FreeAndNil()
,程序不会崩溃,但也不会调用析构函数。
什么是优雅的解决方案?
- 我的程序中有很多这样的
Free
。当然,将Free
代码转移到其他地方是可以的,但我希望它更优雅。 - 程序需要在 Windows 中编译回 XE2,在 Linux 10.2。我读到 10.3 省略了 ARC,这可能会解决问题,但 10.3 很昂贵。
- 需要更改程序并且
{$IFDEF ...}
指令最好最小化。
请告诉我你的建议。
destructor Free; // <-- WRONG!
这是错误的。正确的析构函数称为 Destroy()
,它在 TObject
中是 virtual
,因此您需要在派生 类:
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()
是一个非虚拟实例方法,如果 Self
不是 nil
,则调用 Destroy()
析构函数。
在 ARC 系统上,编译器会自动将所有对 Free()
的调用替换为 nil
赋值,从而减少对象的引用计数。这样可以在 ARC 和非 ARC 系统上使用具有相似语义的相同代码。对象的 Destroy()
析构函数在其引用计数降至 0 时被调用。