TObject.InstanceSize返回8,但是TObject没有声明任何数据成员。根据TObject.ClassType的实现,前4个字节可以解释为指向对象的TClass元数据的指针。有人知道其他4个字节的开销是用来做什么的吗?
编辑:显然这是特定于D2009的。在旧版本中,它只有4个字节。
发布于 2009-03-24 20:12:50
在Delphi2009中,有the ability to have a reference to a synchronization monitor。请参见:
class function TMonitor.GetFieldAddress(AObject: TObject): PPMonitor;
class function TMonitor.GetMonitor(AObject: TObject): PMonitor;...in System.pas
此外,还有一个指向VMT的指针。(虚方法表) From :
TObject类声明了几个方法和一个特殊的隐藏字段来存储对对象类的引用。这个隐藏字段指向类的虚方法表(VMT)。每个类都有一个唯一的VMT,该类的所有对象都共享该类的VMT。
发布于 2009-03-24 21:00:31
对象包含其所有字段的条目,以及用于保存指向虚拟方法表的指针的额外空间。VMT包含的不仅仅是虚方法指针。我在我的网站上解释了more about the VMT,包括一个图表。
显然,Delphi2009除了使用VMT指针来保存同步监视器之外,还引入了另一个隐藏字段。您可以使用一些简单的代码来确定它是添加在类的开头还是结尾:
type
TTest = class
FField: Integer;
end;
var
obj: TTest;
ObjAddr, FieldAddr: Cardinal;
begin
Assert(TTest.InstanceSize = 12);
obj := TTest.Create;
ObjAddr := Cardinal(obj);
FieldAddr := Cardinal(@(obj.FField));
writeln(FieldAddr - ObjAddr);
end.如果输出的值是4,那么monitor字段必须位于对象的末尾,因为4只考虑了VMT指针的大小。如果打印的值为8,则monitor字段必须位于起始位置,与VMT指针相邻。
我希望你一开始就能找到显示器。否则,这意味着后代对象的布局不仅仅是附加了所有新字段的基对象的布局。这意味着monitor字段的偏移量取决于对象的运行时类型,这使得实现更加复杂。
当一个类实现一个接口时,对象布局包含更多的隐藏字段。这些字段包含指向对象的接口引用值的指针。当您有一个对象的IUnknown引用时,它持有的指针与指向对象的VMT字段的指针不同,后者是您使用普通对象引用时所拥有的。IUnknown指针值将是隐藏字段的地址。我已经编写了more about the layout of classes that implement interfaces。
发布于 2009-03-25 06:40:48
如果有人想知道为什么Craig Stuntz的答案被指责,请看他对这个答案的最后一条评论:
看起来像是在D2009:http://blogs.embarcadero.com/abauer/2008/02/19/38856中添加的,有关详细信息,请参阅该帖子中的链接。
链接不再可用,但has but机器有它:
https://web.archive.org/web/20160409224957/blogs.embarcadero.com/abauer/2008/02/19/38856
https://stackoverflow.com/questions/679022
复制相似问题