Ich muss meinen Code nach der Fertigstellung der SysUtils-Einheit ausführen.Einheit Finalisierungsreihenfolge für Anwendung, kompiliert mit Laufzeitpaketen?
Ich habe meinen Code in separate Einheit platziert und enthalten zunächst in uses-Klausel des DPR-Datei, wie folgt aus:
project Project1;
uses
MyUnit, // <- my separate unit
SysUtils,
Classes,
SomeOtherUnits;
procedure Test;
begin
//
end;
begin
SetProc(Test);
end.
MyUnit sieht wie folgt aus:
unit MyUnit;
interface
procedure SetProc(AProc: TProcedure);
implementation
var
Test: TProcedure;
procedure SetProc(AProc: TProcedure);
begin
Test := AProc;
end;
initialization
finalization
Test;
end.
Beachten Sie, dass MyUnit hat keine Verwendung.
Dies ist übliche Windows-EXE, keine Konsole, ohne Formulare und mit Standard-Laufzeit-Paketen kompiliert. MyUnit ist nicht Teil eines Pakets (aber ich habe versucht, es auch aus dem Paket zu verwenden).
Ich erwarte, dass Finalisierung Abschnitt von MyUnit nach Finalisierung Abschnitt von SysUtils ausgeführt wird. Das ist es, was Delphi mir erzählt.
Dies ist jedoch nicht immer der Fall.
Ich habe 2 Test-Apps, die ein wenig nach Code in Test-Routine/dpr-Datei und Einheiten unterscheidet, in Anwendungen aufgeführt. MyUnit wird jedoch in allen Fällen zuerst aufgeführt.
Eine Anwendung ausgeführt wird, wie erwartet: Halt0 -> FinalizeUnits -> ... andere Einheiten ... -> SysUtils der Finalisierung -> MyUnit der Finalisierung -> ... andere Einheiten ...
Aber das zweite ist nicht. MyUnit Finalisierung wird vor SysUtils Finalisierung aufgerufen. Die eigentliche Aufrufkette sieht so aus: Halt0 -> FinalizeUnits -> ... andere Einheiten ... -> SysUtils Finalisierung (übersprungen) -> MyUnit Finalisierung -> ... andere Einheiten ... -> SysUtils Finalisierung (ausgeführt)
Beide Projekte haben sehr ähnliche Einstellungen. Ich habe viel versucht, ihre Unterschiede zu beseitigen/zu minimieren, aber ich sehe immer noch keinen Grund für dieses Verhalten.
Ich habe versucht, dies zu debuggen und herausgefunden, dass: es scheint, dass jede Einheit eine Art von Referenz zählen. Und es scheint, dass InitTable mehrfache Referenzen auf dieselbe Einheit enthält. Wenn der Finalisierungsabschnitt von SysUtils zum ersten Mal aufgerufen wird, ändert er den Referenzzähler und tut nichts. Dann wird die Finalisierung von MyUnit ausgeführt. Und dann wird SysUtils wieder genannt, aber diesmal Referenzzählung Null erreicht und Finalisierung Abschnitt ausgeführt wird:
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
...
Kann jemand kann Licht zerkleinern zu diesem Thema? Fehle ich etwas?
> Gibt es einen besonderen Grund, warum Ihr MyUnit nach SysUtils abschließen muss? Ja. Es ist Mem-Leaking-Checks. – Alex
@Alexander: Macht es etwas Besonderes, das Sie mit FastMM im FullDebugMode nicht erreichen können? –
> Macht es etwas Besonderes, das Sie mit FastMM im FullDebugMode nicht erreichen können? Das ist nicht die Frage, die ich stelle, also lass es beiseite. FastMM hat in meiner zweiten App genau aus dem gleichen Grund nicht funktioniert: es heißt viel zu früh. – Alex