Ordem de finalização da unidade para o aplicativo, compilada com pacotes de tempo de execução?

Preciso executar meu código após a finalização da unidade SysUtils.

Coloquei meu código em uma unidade separada e o incluí primeiro na cláusula uses do dpr-file, assim:

project Project1;

uses
  MyUnit,    // <- my separate unit
  SysUtils,
  Classes,
  SomeOtherUnits;

procedure Test;
begin
  //
end;

begin
  SetProc(Test);
end.

MyUnit é assim:

unit MyUnit;

interface

procedure SetProc(AProc: TProcedure);

implementation

var
  Test: TProcedure;

procedure SetProc(AProc: TProcedure);
begin
  Test := AProc;
end;

initialization

finalization
  Test;
end.

Observe que MyUnit não tem nenhum uso.

Esse é o exe comum do Windows, sem console, sem formulários e compilado com pacotes de tempo de execução padrão. MyUnit não faz parte de nenhum pacote (mas eu tentei usá-lo também).

Espero que a seção de finalização do MyUnit seja executada após a seção de finalização do SysUtils. Isto é o que a ajuda de Delphi me diz.

No entanto, esse nem sempre é o caso.

Eu tenho 2 aplicativos de teste, que diferem um pouco do código na rotina de teste / arquivo dpr e unidades, listadas nos usos. MyUnit, no entanto, é listado primeiro em todos os casos.

Um aplicativo é executado conforme o esperado:Halt0 -> FinalizeUnits -> ... outras unidades ... -> finalização do SysUtils -> finalização do MyUnit -> ... outras unidades ...

Mas o segundo não é. A finalização do MyUnit é invocadaantes Finalização do SysUtils. A cadeia de chamadas real é assim:Halt0 -> FinalizeUnits -> ... outras unidades ... -> Finalização do SysUtils (ignorada) -> Finalização do MyUnit -> ... outras unidades ... -> Finalização do SysUtils (executada)

Ambos os projetos têm configurações muito semelhantes. Tentei muito remover / minimizar as diferenças, mas ainda não vejo uma razão para esse comportamento.

Eu tentei depurar isso e descobri o seguinte: parece que cada unidade tem algum tipo de contagem de referência. E parece que InitTable contém referências multiplicadas para a mesma unidade. Quando a seção de finalização do SysUtils é chamada pela primeira vez - ele altera o contador de referência e não faz nada. A finalização do MyUnit é executada. E então o SysUtils é chamado novamente, mas desta vez ref-count chega a zero e a seção de finalização é executada:

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
...

Alguém pode esclarecer essa questão? Estou esquecendo de algo?

questionAnswers(4)

yourAnswerToTheQuestion