delphi - 错误地调用继承会造成什么损害?

标签 delphi

在 Delphi XE 程序中搜索高度间歇性内存损坏时,我发现了一个类构造函数,它初始化类中的一些字段,然后调用继承。我相信初始化是在第一次编写构造函数之后添加的,并且意外地添加到了错误的位置。我现在已将其更正为首先调用继承。内存损坏的异常几乎总是发生在此类的方法中。

问题:这个错误是否有可能导致间歇性内存损坏?在跟踪代码时,似乎没有,但我真的希望这个修复能够解决间歇性问题。解决问题后一段时间不再出现并不能证明问题已经消失。

一些代码:

Tmyclass = class
  ctype : integer;
  ts : tstringlist;
  th : thandle;
public
  Constructor Create;
  Destructor Destroy; override;
  ...
end;

Constructor Tmyclass.Create;
begin
  ctype := 3;
  doinit;
  inherited;
end;

最佳答案

以下是对象创建的典型步骤:

  • 对象实例的内存分配;
  • 用零填充所有内存(以初始化所有字段,尤其是字符串);
  • 从最新的子级开始,调用所有嵌套构造函数,让 inherited 调用每个父级 - 这就是为什么您应在构造函数和析构函数中编写 inherited

因此,inherited 调用父方法 - 您甚至可以指定父级别,或者如果您确定可以做到这一点,则不调用任何父方法(但可能会违反 SOLID 原则)。

事实上,当调用构造函数时,方法中添加了一个隐藏参数:

Constructors and destructors use the same calling conventions as other methods, except that an additional Boolean flag parameter is passed to indicate the context of the constructor or destructor call.

A value of False in the flag parameter of a constructor call indicates that the constructor was invoked through an instance object or using the inherited keyword. In this case, the constructor behaves like an ordinary method. A value of True in the flag parameter of a constructor call indicates that the constructor was invoked through a class reference. In this case, the constructor creates an instance of the class given by Self, and returns a reference to the newly created object in EAX.

A value of False in the flag parameter of a destructor call indicates that the destructor was invoked using the inherited keyword. In this case, the destructor behaves like an ordinary method. A value of True in the flag parameter of a destructor call indicates that the destructor was invoked through an instance object. In this case, the destructor deallocates the instance given by Self just before returning.

The flag parameter behaves as if it were declared before all other parameters. Under the register convention, it is passed in the DL register. Under the pascal convention, it is pushed before all other parameters. Under the cdecl, stdcall, and safecall conventions, it is pushed just before the Self parameter.

来源:official Delphi documentation

因此您可以确信,无论在何处调用 inherited,它都会得到安全处理。例如,在调用所有构造函数之前,字段的初始化(重置为 0)将仅处理一次。

TObject.Create 默认构造函数(在 inherited 行中调用的构造函数)只是一个 begin end void block ,它不执行任何操作。在这里调用 inherited 甚至不是必要/强制的,但这是一个好习惯,因为如果您更改对象层次结构,那么最终可能需要它。

唯一的问题可能是,如果在子级中设置某些字段后,在此继承方法中设置某些字段(例如ctype := 2),但这不是编译器的错误,这取决于用户代码!

关于delphi - 错误地调用继承会造成什么损害?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8690207/

相关文章:

ios - Delphi XE2 Firemonkey iOS 应用控制兼容性

android - SDK 25 是否终止了对 Android 版 Firemonkey 的支持?

delphi - 在 DirectShow Filter 的 EnumPins 方法(Delphi/DSPACK)中处理 NULL ppPins 参数的正确方法?

delphi - 如何使用 Delphi 中的 Indy 客户端从服务器读取所有字节?

delphi - 如何在DLL(Delphi/TJVPluginManager + TJvPlugin)中实现回调方法

Delphi XE - TRibbon 操作始终将焦点发送到 MainForm

multithreading - 如何让delphi等待30秒然后继续

Delphi 记录中的字符串列表

delphi - 自动检测应用程序 "Type"

windows - 如何检测 Delphi 7 上的 Windows Aero 主题?