SysUtilsユニットのファイナライズ後にコードを実行する必要があります。
コードを別のユニットに配置し、最初に次のようにdpr-fileのuses句に含めました。
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には用途がないことに注意してください。
これは通常のWindowsexeであり、コンソールはなく、フォームがなく、デフォルトのランタイムパッケージでコンパイルされています。MyUnitはパッケージの一部ではありません(ただし、パッケージからも使用しようとしました)。
MyUnitのファイナライズセクションは、SysUtilsのファイナライズセクションの後に実行されることを期待しています。これはDelphiの助けが私に教えてくれることです。
ただし、これが常に当てはまるとは限りません。
私は2つのテストアプリを持っていますが、テストルーチン/dprファイルとユニットのコードによって少し異なります。ただし、すべての場合でMyUnitが最初にリストされます。
1つのアプリケーションが期待どおりに実行されます:Halt0-> FinalizeUnits-> ... other units...->SysUtilsのファイナライズ->MyUnitのファイナライズ->...other units .. ..
しかし、2番目はそうではありません。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
...
誰でもこの問題に光を当てることができますか?私は何かが足りないのですか?