2017-11-21 13 views
1

以下のサンプルコードがあります デルファイコンパイラがすべてのメモリ割り当てを解放しない理由を説明できる人は です。私は解放メソッドを使用してTLoginFormを破壊するためにfreeメソッドを使用していません。どこにもあなたのコード内リリースを完了するにはどうすればいいですか?

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; 

答えて

1

あなたはnilに変数LoginFormを設定します。したがって、それが参照するオブジェクトが破棄された後でもその値は保持されます。この変数をnilに設定するには、明示的にそれを実行する必要があります。

あなたが参考に関連する質問にこの答えを見つける必要があり

https://stackoverflow.com/a/8550628/本質的には

、あなたの質問の背後にある問題は、おそらくより良いこの簡単な例を理解することができる。

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

オブジェクトの破棄はしていませんそれを参照する変数をクリアします。

はい、あなたのコードではFreeではなくReleaseを使用しますが、基本的な概念はまったく同じです。

+0

Davidさん、まあ、私はdoLogoutで納得できる理由でチェックをした理由を確認します。だから私のチェックの方法は、それを無関係と比較すると間違っていた。 https://stackoverflow.com/a/8550628/は私にとって役に立ちました。 –

2

Release()は遅延破棄です。それはCM_RELEASEメッセージをフォームに投稿し、フォームはそのメッセージを処理するときにFreeを呼び出します。

Formオブジェクト(またはそれ以外のオブジェクト)を解放しても、そのオブジェクトへのポインタは自動的にnilに設定されません。独自のコードで手動で行う必要があります。この場合、のデストラクタまたはOnDestroyイベントで、グローバルLoginFormポインタをnilに設定することができます。

Release()を直接呼び出す代わりに、TLoginForm.OnCloseイベントの使用を検討することもできます。 doLogin()Close()とし、フォームが実際に閉じられたら、ActionパラメーターをcaFreeに設定して、フォームを解放します(Release()経由)。ただし、ポインタを手動でnilに手動で設定する必要があります。

関連する問題