2017-11-21 3 views
1

Ich habe Beispielcode unter kann jemand erklären, warum Delphi Compiler nicht alle Speicherzuweisung für Objekt freigeben, so dass keine Überprüfung immer wahr ist. im benutze release-Methode für die Zerstörung von TLoginForm im nicht mit freien Methode, weil das gab mir Ausnahme, wenn einige Schnittstelle Ereignis zuvor kostenlos oder danach aufgerufen.So vervollständigen Release Child Form von Speicherzuweisung

type 
    TMainForm = class(TForm) 
    {some stuf} 
    public 
    procedure Create(AOwner: TComponent); override; 
    procedure doLogout(); 
    end; 

    TChildBase = class(TForm) 
    {some stuf} 
    public 
    procedure Create(AOwner: TComponent); override; 
    end; 

    TLoginForm = class(TChildBase) 
    public 
    procedure doLogin(); 
    end; 

var 
    MainForm: TMainForm; {<== created automaticaly at runtime} 
    LoginForm: TLoginForm; {<== created at create event in TMainForm} 

implementation 

{TLoginForm} 
procedure TLoginForm.doLogin; 
begin 
    if true then 
    begin 
    { Do Interfaced Event to main form } 
    Release; 
    end; 
end; 

procedure TMainForm.Create(AOwner: TComponent); 
begin 
    inherited; 
    FormStyle := fsMDIForm; 
    LoginForm := TLoginForm.Create(Application); {Create login form} 
end; 

procedure TMainForm.doLogout; 
begin 
    { Do Interfaced Event to Child Form except TLoginForm to close} 

    if LoginForm <> nil then {<== this still alocated at memory} 
    LoginForm := TLoginForm.Create(Application) 
    else 
    LoginForm.Show; {<== Error raised here.} 
end; 

Antwort

1

Nirgendwo in Ihrem Code richten Sie die Variable LoginForm-nil. So behält es seinen Wert, auch nachdem das Objekt, auf das es sich bezieht, zerstört wurde. Wenn Sie möchten, dass diese Variable auf nil gesetzt wird, müssen Sie dies explizit tun.

Sie diese Antwort auf eine ähnliche Frage hilfreich soll: https://stackoverflow.com/a/8550628/

Im Wesentlichen das Problem hinter Ihrer Frage besser mit diesem einfachen Beispiel zu verstehen kann vielleicht sein:

obj := TObject.Create; 
obj.Free; 
Assert(Assigned(obj)); 

Destroying ein Objekt nicht Löschen Sie die Variablen, die sich darauf beziehen.

Ja, in Ihrem Code verwenden Sie Release statt Free, aber das grundlegende Konzept ist genau das gleiche.

+0

Herr David, Sie haben Recht, ich überprüfe den Grund, wenn ich aus triftigem Grund die Überprüfung bei DoLogout setze. also war meine Methode zur Überprüfung falsch, wenn man sie mit Null vergleicht. https://stackoverflow.com/a/8550628/ war hilfreich für mich. –

2

Release() ist nur eine verzögerte Zerstörung. Es sendet eine Nachricht an das Formular und dann ruft das Formular Free auf sich selbst auf, wenn es diese Nachricht verarbeitet.

Durch das Freigeben eines Formularobjekts (oder eines anderen Objekts) werden alle Zeiger auf dieses Objekt nicht automatisch auf null gesetzt. Sie müssen das manuell in Ihrem eigenen Code tun. In diesem Fall können Sie den globalen Zeiger LoginForm in TLoginForm Destruktor oder OnDestroy-Ereignis auf Null festlegen.

Sie könnten auch das Ereignis TLoginForm.OnClose anstelle von Release() direkt verwenden. Haben Sie doLogin() Anruf Close(), und wenn das Formular tatsächlich geschlossen ist, setzen Sie den Action Parameter des Ereignisses auf caFree, so dass das Formular sich freigibt (über Release()). Sie müssen den globalen Zeiger LoginForm jedoch manuell auf nil setzen.