Если вы достаточно глубоко погрузитесь в внутреннее устройство компилятора Delphi, вы можете столкнуться с чем-то странным и, по-видимому, не задокументированным в записях TTypeInfo, сгенерированных компилятором. Если указатель PTypeInfo указывает на запись TTypeInfo по адресу X, то по адресу X - 4 вы найдете следующие 4 байта, которые описывают указатель на X. Например, рассмотрим следующий код:
Если передать в эту функцию любой легитимный PTypeInfo, сгенерированный компилятором, она выведет один и тот же адрес дважды. Исследуя TypInfo.pas, я не нашел ничего, что упоминало бы этот "identity pointer" или объясняло его назначение. Это явление наблюдается во всех версиях Delphi, начиная least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least что это за указатель на "идентичность", и зачем он там находится. Это явление присутствует во всех версиях Delphi, начиная хотя least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least least что структура TTypeInfo содержит внутренний указатель, который указывает на саму структуру. Этот указатель расположен за четыре байта до начала структуры и, судя по всему, предназначен для использования в случае динамической компоновки.
Подтвержденный ответ
Причина довольно проста: пакеты и динамическая компоновка. BPL-файлы (Borland Package Library) фактически являются динамически подключаемыми библиотеками (DLL). В операционных системах, поддерживающих динамическую компоновку, программы могут загружать и использовать код из таких библиотек во время выполнения, вместо того чтобы включать его в свой собственный исполняемый файл. Для того чтобы избежать необходимости в изменении ссылки на TypeInfo в коде или в исполняемом файле при динамической компоновке, используется механизм перенаправления через таблицы импорта.
Это становится очевидным, если сравнить статическую и динамическую компоновку в следующем программе:
program TestTypeInfo;
{$APPTYPE CONSOLE}
uses
TypInfo,
SysUtils;
type
TFoo = class(TObject);
var
x: PPTypeInfo;
begin
x := GetTypeData(TypeInfo(TFoo))^.ParentInfo;
Writeln(x^^.Name);
Writeln(Format('x %p', [x]));
Writeln(Format('x^ %p', [x^]));
end.
Компилируя программу с помощью dcc32 test.pas, вы получите один набор адресов, а если использовать RTL-пакет с dcc32 -LUrtl test.pas, то другой. Это связано с тем, что при динамической компоновке ссылки на TypeInfo перенаправляются через таблицы импорта, что и обуславливает наличие дополнительного указателя перед структурой TTypeInfo.
Заключение
Таким образом, указатель на "идентичность", расположенный за четыре байта до начала структуры TTypeInfo, является частью механизма, обеспечивающего корректную работу с типами данных в условиях динамической компоновки. Это позволяет избежать необходимости изменения ссылок на TypeInfo при подключении библиотек в динамическом режиме.
При разработке на Delphi, обнаружено недокументированное свойство `TTypeInfo` – 'identity pointer', который используется для обеспечения корректной работы с типами данных в условиях динамической компоновки, позволяя избежать необходимости и
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.