簡體   English   中英

TObject 包含哪些數據?

[英]What data does a TObject contain?

TObject.InstanceSize 返回 8,但 TObject 沒有聲明任何數據成員。 根據 TObject.ClassType 的實現,前 4 個字節可以解釋為指向對象的 TClass 元數據的指針。 有人知道其他 4 個字節的開銷是做什么用的嗎?

編輯:顯然這是特定於 D2009。 在舊版本中,它只有 4 個字節。

在 Delphi 2009 中, 可以引用同步監視器 看:

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

...在 System.pas

此外,還有一個指向 VMT 的指針。 (虛擬方法表。)簡而言之,來自 Delphi

TObject class 聲明了幾種方法和一個特殊的隱藏字段來存儲對對象 class 的引用。 此隱藏字段指向類的虛擬方法表 (VMT)。 每個 class 都有一個唯一的 VMT,並且該 class 的所有對象共享該類的 VMT。

object 包含其所有字段的條目,以及用於保存指向虛擬方法表的指針的額外空間。 VMT 不僅僅包含虛擬方法指針。 我在我的 Web 站點上解釋了更多關於 VMT的信息,包括一個圖表。

顯然,Delphi 2009 除了用於保存同步監視器的 VMT 指針外,還引入了另一個隱藏字段。 您可以通過一些簡單的代碼來確定它是添加在 class 的開頭還是結尾:

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,則監視字段必須位於 object 的末尾,因為 4 僅說明 VMT 指針的大小。 如果它打印值 8,則監視器字段必須位於開頭,與 VMT 指針相鄰。

我希望你會在一開始就找到監視器。 否則,這意味着后代 object 的布局不僅僅是附加了所有新字段的基本 object 的布局。 這意味着監視字段的偏移量取決於 object 的運行時類型,這使得實現更加復雜。

當 class 實現接口時,object 布局包含更多隱藏字段。 這些字段包含指向對象的接口引用值的指針。 當你有一個對 object 的IUnknown引用時,它持有的指針與指向對象的 VMT 字段的指針不同,這與普通的 object 引用相同。 IUnknown指針值將是隱藏字段的地址。 我已經寫了更多關於實現接口的類的布局

萬一有人想知道為什么 Craig Stuntz 的回答被接受了,請參閱他對該回答的最后評論:

看起來像是在 D2009 中添加的: http://blogs.embarcadero.com/abauer/2008/02/19/38856有關詳細信息,請參閱該帖子中的鏈接。

鏈接不再可用,但wayback-machine 有它:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM