在Delphi XE程序中搜索高度间歇性的内存损坏时,我找到了一个类构造函数,它初始化类中的几个字段,然后调用inherited.我相信初始化是在构造函数首次编写后添加的,并且意外地在错误的位置.我现在已经纠正它,先调用继承.内存损坏的例外几乎总是发生在这个类的方法中.
问题:这个错误是否可能导致间歇性内存损坏?在跟踪代码时,似乎没有,但我真的希望这个解决方案可以解决间歇性问题.在解决问题后一段时间内没有发生这种情况并不能证明它已经消失了.
一些代码:
Tmyclass = class
ctype : integer;
ts : tstringlist;
th : thandle;
public
Constructor Create;
Destructor Destroy; override;
...
end;
Constructor Tmyclass.Create;
begin
ctype := 3;
doinit;
inherited;
end;
Run Code Online (Sandbox Code Playgroud)
以下是对象创建的典型步骤:
inherited节点开始,让每个父节点调用 - 这就是你应该inherited在构造函数和析构函数中编写的原因.因此,inherited调用父方法 - 您甚至可以指定父级别,或者如果您确定可以执行此操作则调用none(但可能会违反SOLID原则).
实际上,当constructor调用a时,会在方法中添加一个隐藏参数:
构造函数和析构函数使用与其他方法相同的调用约定,除了传递额外的Boolean标志参数以指示构造函数或析构函数调用的上下文.
构造函数调用的flag参数中的值False表示构造函数是通过实例对象或使用inherited关键字调用的.在这种情况下,构造函数的行为类似于普通方法.构造函数调用的flag参数中的值True表示构造函数是通过类引用调用的.在这种情况下,构造函数创建Self提供的类的实例,并返回对EAX中新创建的对象的引用.
析构函数调用的flag参数中的值False表示使用inherited关键字调用析构函数.在这种情况下,析构函数的行为类似于普通方法.析构函数调用的flag参数中的值True表示通过实例对象调用析构函数.在这种情况下,析构函数在返回之前释放Self给出的实例.
flag参数的行为就像在所有其他参数之前声明一样.根据寄存器约定,它在DL寄存器中传递.在pascal约定下,它在所有其他参数之前被推送.在cdecl,stdcall和safecall约定下,它在Self参数之前被推送.
来源:官方Delphi文档
因此,您可以确定,无论何处inherited调用,都可以安全地处理.例如,在调用所有构造函数之前,字段的初始化(重置为0)将仅处理一次.
该TObject.Create默认构造函数(一个叫你inherited行)只是一个begin end空白块,它什么都不做.inherited在这里调用它甚至没有必要/强制,但这是一个好习惯,因为如果你改变你的对象层次结构,它可能是需要的.
唯一的问题可能是,如果在子inherited方法中设置了一些字段(ctype := 2例如),但是这不是编译器的错误,这取决于用户代码!
| 归档时间: |
|
| 查看次数: |
220 次 |
| 最近记录: |