Мне нужно выполнить мой код после завершения модуля SysUtils.
Я поместил свой код в отдельный модуль и сначала включил его в раздел использования dpr-файла, например:
project Project1;
uses
MyUnit, // <- my separate unit
SysUtils,
Classes,
SomeOtherUnits;
procedure Test;
begin
//
end;
begin
SetProc(Test);
end.
MyUnit выглядит так:
unit MyUnit;
interface
procedure SetProc(AProc: TProcedure);
implementation
var
Test: TProcedure;
procedure SetProc(AProc: TProcedure);
begin
Test := AProc;
end;
initialization
finalization
Test;
end.
Обратите внимание, что MyUnit не используется.
Это обычный Windows exe, без консоли, без форм и скомпилированный с пакетами времени выполнения по умолчанию. MyUnit не является частью какого-либо пакета (но я тоже пытался использовать его из пакета).
Я ожидаю, что раздел финализации MyUnit будет выполнен после раздела финализации SysUtils. Это то, что мне подсказала помощь Delphi.
Тем не менее, это не всегда так.
У меня есть 2 тестовых приложения, которые немного отличаются по коду в тестовой подпрограмме/dpr-файле и модулях, перечисленных в использовании. MyUnit, однако, во всех случаях указывается первым.
Одно приложение запускается как положено: Halt0 -> FinalizeUnits -> ...другие модули... -> финализация SysUtils -> финализация MyUnit -> ...другие модули...
Но второй нет. Финализация MyUnit вызывается до финализации SysUtils. Фактическая цепочка вызовов выглядит следующим образом: Halt0 -> FinalizeUnits -> ...другие модули... -> финализация SysUtils (пропущена) -> финализация MyUnit -> ...другие модули... -> финализация SysUtils (выполнено)
Оба проекта имеют очень похожие настройки. Я много пытался убрать/свести к минимуму их различия, но до сих пор не вижу причины такого поведения.
Я попытался отладить это и обнаружил следующее: кажется, что у каждого модуля есть какой-то подсчет ссылок. И кажется, что InitTable содержит несколько ссылок на один и тот же модуль. Когда секция финализации SysUtils вызывается в первый раз, она меняет счетчик ссылок и ничего не делает. Затем выполняется финализация MyUnit. Затем снова вызывается SysUtils, но на этот раз ref-count достигает нуля и выполняется секция финализации:
Finalization: // SysUtils' finalization
5003B3F0 55 push ebp // here and below is some form of stub
5003B3F1 8BEC mov ebp,esp
5003B3F3 33C0 xor eax,eax
5003B3F5 55 push ebp
5003B3F6 688EB50350 push $5003b58e
5003B3FB 64FF30 push dword ptr fs:[eax]
5003B3FE 648920 mov fs:[eax],esp
5003B401 FF05DCAD1150 inc dword ptr [$5011addc] // here: some sort of reference counter
5003B407 0F8573010000 jnz $5003b580 // <- this jump skips execution of finalization for first call
5003B40D B8CC4D0350 mov eax,$50034dcc // here and below is actual SysUtils' finalization section
...
Может ли кто-нибудь пролить свет на этот вопрос? Я что-то упускаю?