I need to execute my code after finalizing the SysUtils block.
I put my code in a separate block and first included it in the uses dpr sentence of the file, for example:
project Project1; uses MyUnit, // <- my separate unit SysUtils, Classes, SomeOtherUnits; procedure Test; begin // end; begin SetProc(Test); end.
MyUnit looks like this:
unit MyUnit; interface procedure SetProc(AProc: TProcedure); implementation var Test: TProcedure; procedure SetProc(AProc: TProcedure); begin Test := AProc; end; initialization finalization Test; end.
Please note that MyUnit does not have any uses.
This is a regular Windows exe, without a console, without forms, and compiled with default runtime packages. MyUnit is not part of any package (but I also tried to use it from the package).
I expect the MyUnit completion section to be executed after the SysUtils completion section. This is what Delphi helps me.
However, this is not always the case.
I have 2 test applications that differ slightly in code in the test procedure / dpr file and the units listed in the applications. However, MyUnit is listed first in all cases.
One application starts as expected: Halt0 β FinalizeUnits β ... other units ... β Finalize SysUtils β Finalize MyUnit β ... other units ...
But the second is not. The finalization of MyUnit is called before the completion of SysUtils. The actual call chain is as follows: Halt0 β FinalizeUnits β ... other units ... β Finalize SysUtils (skipped) β Finalize MyUnit β ... other units ... β Final SysUtils (in progress)
Both projects have very similar settings. I tried a lot to remove / minimize their differences, but I still see no reason for this behavior.
I tried to debug this and found out that: it seems that every unit has some kind of reference count. And it looks like InitTable contains multiple references to the same unit. When the SysUtils completion section is called for the first time, it changes the reference count and does nothing. Then MyUnit is finalized. And then SysUtils is called again, but this time ref-count reaches zero, and the completion section ends:
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 ...
Can anyone highlight this issue? Am I missing something?