TObject 包含哪些数据?

发布于 2024-07-16 07:34:02 字数 181 浏览 5 评论 0 原文

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

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

TObject.InstanceSize returns 8, yet TObject doesn't declare any data members. According to the implementation of TObject.ClassType, the first 4 bytes can be explained as a pointer to the object's TClass metadata. Anyone know what the other 4 bytes of overhead are there for?

EDIT: Apparently this is specific to D2009. In older versions, it's only 4 bytes.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

貪欢 2024-07-23 07:34:02

在Delphi 2009中,有 能够引用同步监视器。 请参阅:

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

...在 System.pas 中

此外,仍然有一个指向 VMT 的指针。 (虚拟方法表。)来自 Delphi 简而言之:< /a>

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

In Delphi 2009, there is the ability to have a reference to a synchronization monitor. See:

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

...in System.pas

Also, there is still a pointer to the VMT. (Virtual Method Table.) From Delphi in a Nutshell:

The TObject class declares several
methods and one special, hidden field
to store a reference to the object's
class. This hidden field points to the
class's virtual method table (VMT).
Every class has a unique VMT and all
objects of that class share the
class's VMT.

遮云壑 2024-07-23 07:34:02

对象包含其所有字段的条目,以及用于保存指向虚拟方法表的指针的额外空间。 VMT 不仅仅保存虚拟方法指针。 我在我的网站上解释了有关 VMT 的更多信息,包括一张图表。

显然,Delphi 2009除了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,则监视器字段必须位于对象的末尾,因为 4 只占对象的大小VMT 指针。 如果它打印值 8,则监视器字段必须位于开头,与 VMT 指针相邻。

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

当类实现接口时,对象布局包含更多隐藏字段。 这些字段包含指向对象的接口引用值的指针。 当您拥有对某个对象的 IUnknown 引用时,它所持有的指针与指向该对象的 VMT 字段的指针不同,后者与普通对象引用所具有的指针不同。 IUnknown 指针值将是隐藏字段的地址。 我写了有关实现接口的类的布局的更多信息

An object contains entries for all its fields, plus extra space to hold a pointer to the virtual-method table. The VMT holds more than just virtual-method pointers. I explain more about the VMT at my Web site, including a diagram.

Apparently, Delphi 2009 introduces another hidden field in addition to the VMT pointer to hold the synchronization monitor. You can determine whether it is added at the beginning or at the end of the class with some simple code:

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.

If it prints the value 4, then the monitor field must be at the end of the object because 4 only accounts for the size of the VMT pointer. If it prints the value 8, then the monitor field must be at the start, adjacent to the VMT pointer.

I expect you'll find the monitor at the start. Otherwise, it means that the layout of the descendant object isn't simply the layout of the base object with all the new fields appended. It would mean the offset of the monitor field depends on the run-time type of the object, and that makes the implementation more complicated.

When a class implements an interface, the object layout includes more hidden fields. The fields contain pointers to the object's interface-reference value. When you have an IUnknown reference to an object, the pointer it holds isn't the same as the pointer to the object's VMT field, which is what you have with an ordinary object reference. The IUnknown pointer value will be the address of the hidden field. I've written more about the layout of classes that implement interfaces.

中性美 2024-07-23 07:34:02

以防万一有人想知道为什么 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

Just in case somebody is wondering why Craig Stuntz' answer was accpepted, see his last comment on that answer:

Looks like was added in D2009: http://blogs.embarcadero.com/abauer/2008/02/19/38856 See links in that post for full details.

Link no longer available, but the wayback-machine has it:

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文