TObject包含哪些数据?

问题描述 投票:8回答:3

TObject.InstanceSize返回8,但TObject没有声明任何数据成员。根据TObject.ClassType的实现,前4个字节可以解释为指向对象的TClass元数据的指针。任何人都知道其他4个字节的开销是什么?

编辑:显然这是D2009特有的。在旧版本中,它只有4个字节。

delphi object delphi-2009 tobject
3个回答
12
投票

在Delphi 2009中,有the ability to have a reference to a synchronization monitor。看到:

class function TMonitor.GetFieldAddress(AObject: TObject): PPMonitor;
class function TMonitor.GetMonitor(AObject: TObject): PMonitor;

...在System.pas中

此外,仍然有一个指向VMT的指针。 (虚拟方法表。)From Delphi in a Nutshell:

TObject类声明了几个方法和一个特殊的隐藏字段来存储对象类的引用。该隐藏字段指向类的虚方法表(VMT)。每个类都有一个唯一的VMT,该类的所有对象共享该类的VMT。


3
投票

对象包含其所有字段的条目,以及用于保存指向虚方法表的指针的额外空间。 VMT不仅仅包含虚方法指针。我在我的网站上解释more about the VMT,包括图表。

显然,除了用于保存同步监视器的VMT指针之外,Delphi 2009还引入了另一个隐藏字段。您可以使用一些简单的代码确定是在类的开头还是结尾添加它:

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,则监视字段必须位于对象的末尾,因为4仅考虑VMT指针的大小。如果它打印值8,则监视字段必须位于VMT指针附近的开始处。

我希望你会在一开始就找到显示器。否则,这意味着后代对象的布局不仅仅是附加了所有新字段的基础对象的布局。这意味着监视器字段的偏移量取决于对象的运行时类型,这使得实现更加复杂。

当类实现接口时,对象布局包含更多隐藏字段。这些字段包含指向对象的接口引用值的指针。当你有一个对象的IUnknown引用时,它所持有的指针与指向对象的VMT字段的指针不同,这是普通对象引用所具有的。 IUnknown指针值将是隐藏字段的地址。我写过more about the layout of classes that implement interfaces


-1
投票

如果有人想知道为什么Craig Stuntz的答案得到了接受,请参阅他对该答案的最后评论:

看起来像是在D2009中添加的:http://blogs.embarcadero.com/abauer/2008/02/19/38856有关详细信息,请参阅该帖子中的链接。

链接不再可用,但是返回机器有它:

https://web.archive.org/web/20160409224957/blogs.embarcadero.com/abauer/2008/02/19/38856

© www.soinside.com 2019 - 2024. All rights reserved.