Frage Welche Daten enthält ein TObject?


TObject.InstanceSize gibt 8 zurück, und TObject deklariert keine Datenelemente. Entsprechend der Implementierung von TObject.ClassType können die ersten 4 Bytes als Zeiger auf die TClass-Metadaten des Objekts erklärt werden. Wer weiß, wofür die anderen 4 Bytes Overhead da sind?

EDIT: Anscheinend ist dies spezifisch für D2009. In älteren Versionen sind es nur 4 Bytes.


7
2018-03-24 20:01


Ursprung


Antworten:


In Delphi 2009 gibt es die Möglichkeit, einen Verweis auf einen Synchronisationsmonitor zu haben. Sehen:

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

... in System.pas

Außerdem gibt es immer noch einen Zeiger auf die VMT. (Virtuelle Methodentabelle.) Von Delphi in Kürze:

Die TObject-Klasse deklariert mehrere   Methoden und ein spezielles, verstecktes Feld   um einen Verweis auf das Objekt zu speichern   Klasse. Dieses versteckte Feld zeigt auf die   Klasse der virtuellen Methodentabelle (VMT).   Jede Klasse hat eine einzigartige VMT und alle   Objekte dieser Klasse teilen sich die   VMT der Klasse.


11
2018-03-24 20:12



Ein Objekt enthält Einträge für alle Felder sowie zusätzlichen Speicherplatz für einen Zeiger auf die virtuelle Methodentabelle. Die VMT enthält mehr als nur Zeiger für virtuelle Methoden. Ich erkläre mehr über die VMT auf meiner Website, einschließlich eines Diagramms.

Anscheinend enthält Delphi 2009 ein weiteres verstecktes Feld zusätzlich zum VMT-Zeiger, um den Synchronisationsmonitor zu halten. Sie können feststellen, ob es am Anfang oder am Ende der Klasse mit einem einfachen Code hinzugefügt wird:

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.

Wenn der Wert 4 ausgegeben wird, muss das Überwachungsfeld am Ende des Objekts stehen, da 4 nur die Größe des VMT-Zeigers berücksichtigt. Wenn der Wert 8 ausgegeben wird, muss das Monitorfeld neben dem VMT-Zeiger stehen.

Ich erwarte, dass Sie den Monitor am Anfang finden werden. Andernfalls bedeutet dies, dass das Layout des untergeordneten Objekts nicht einfach das Layout des Basisobjekts mit allen neuen angefügten Feldern ist. Dies würde bedeuten, dass der Offset des Monitorfelds vom Laufzeittyp des Objekts abhängt und dies die Implementierung komplizierter macht.

Wenn eine Klasse eine Schnittstelle implementiert, enthält das Objektlayout weitere ausgeblendete Felder. Die Felder enthalten Zeiger auf den Schnittstellenreferenzwert des Objekts. Wenn du eine hast IUnknown Referenz auf ein Objekt, der Zeiger, den es hält, ist nicht dasselbe wie der Zeiger auf das VMT-Feld des Objekts, was Sie mit einer gewöhnlichen Objektreferenz haben. Das IUnknown Zeigerwert ist die Adresse des versteckten Feldes. Ich habe geschrieben mehr über das Layout von Klassen, die Schnittstellen implementieren.


3
2018-03-24 21:00



Für den Fall, dass jemand sich fragt, warum Craig Stuntz 'Antwort akzeptiert wurde, siehe seinen letzten Kommentar zu dieser Antwort:

Sieht aus wie in D2009 hinzugefügt wurde: http://blogs.embarcadero.com/abauer/2008/02/19/38856 Siehe Links in diesem Beitrag für alle Details.


0
2018-03-25 06:40