TObject包含哪些数据?

时间:2009-03-24 20:01:34

标签: delphi object delphi-2009 tobject

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

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

3 个答案:

答案 0 :(得分: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类声明了几个   方法和一个特殊的隐藏领域   存储对象的引用   类。这个隐藏的字段指向   class的虚方法表(VMT)。   每个班级都有一个独特的VMT和所有   该类的对象共享   班级的VMT。

答案 1 :(得分: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

答案 2 :(得分:-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