Какие данные содержит TObject?
TObject.InstanceSize возвращает 8, но TObject не объявляет никаких элементов данных. Согласно реализации TObject.ClassType, первые 4 байта могут быть объяснены как указатель на метаданные объекта TClass. Кто-нибудь знает, для чего нужны остальные 4 байта?
РЕДАКТИРОВАТЬ: Очевидно, это относится к D2009. В старых версиях это всего 4 байта.
3 ответа
В Delphi 2009 есть возможность иметь ссылку на монитор синхронизации. Увидеть:
class function TMonitor.GetFieldAddress(AObject: TObject): PPMonitor;
class function TMonitor.GetMonitor(AObject: TObject): PMonitor;
... в System.pas
Также еще есть указатель на VMT. (Таблица виртуальных методов.) Из Delphi в двух словах:
Класс TObject объявляет несколько методов и одно специальное скрытое поле для хранения ссылки на класс объекта. Это скрытое поле указывает на таблицу виртуальных методов класса (VMT). Каждый класс имеет уникальный VMT, и все объекты этого класса совместно используют VMT класса.
Объект содержит записи для всех своих полей, а также дополнительное пространство для хранения указателя на таблицу виртуальных методов. 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
Значение указателя будет адресом скрытого поля. Я написал больше о расположении классов, которые реализуют интерфейсы.
На всякий случай, если кому-то интересно, почему ответ Крейга Стунца был принят, см. Его последний комментарий к этому ответу:
Похоже, что было добавлено в D2009: http://blogs.embarcadero.com/abauer/2008/02/19/38856 Смотрите ссылки в этом посте для получения полной информации.