首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi 對象釋放陷阱與安全釋放模式

     編輯:Delphi

典型錯誤:重複釋放導致崩潰

procedure TForm1.Button1Click(Sender: TObject);
var
  Button2, Button3: TButton;
begin
  Button2 := TButton.Create(Self);
  Button3 := TButton.Create(Button2); // Button2 是 Button3 的 Owner
  Button2.Free;  // 釋放 Button2,同時釋放其擁有的 Button3
  Button3.Free;  // 錯誤!Button3 已被釋放,再次 Free 導致 AV
end;

解決方案 1:釋放順序反向

Button3.Free; // 先釋放子對象
Button2.Free; // 再釋放父對象

解決方案 2:置 nil 防重複釋放

Button2.Free;
Button3 := nil; // 切斷引用
Button3.Free;   // Free 內部判斷 nil 直接返回,安全

TObject.Free 實現:if Self <> nil then Destroy;,置 nil 可避免二次進入 Destroy。

深層原因

  • Destroy 不會將對象引用自動置 nil,內存地址內容短期內仍可讀,誤以為對象存在。
  • 二次調用 Free 會對已釋放內存執行 Destroy,破壞堆管理器元數據,導致不可預測的崩潰。

最佳實踐模式

{ 模式 1: try-finally 確保釋放 }
var Obj: TMyObject;
begin
  Obj := TMyObject.Create;
  try
    // 使用 Obj
  finally
    Obj.Free;
  end;
end;

{ 模式 2: 釋放後立即置 nil (長生命週期字段) }
procedure TForm1.ReleaseObj;
begin
  if FObj <> nil then
  begin
    FObj.Free;
    FObj := nil;
  end;
end;

{ 模式 3: 使用 FreeAndNil (SysUtils) }
FreeAndNil(FObj); // 內部: Free; Pointer := nil;

總結

  • Owner 機制會級聯釋放,注意釋放順序。
  • 長期持有的對象引用,釋放後務必置 nil。
  • 優先使用 FreeAndNil 或 try-finally 規範生命週期。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved