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;
Button3.Free; // 先釋放子對象
Button2.Free; // 再釋放父對象
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;
FreeAndNil 或 try-finally 規範生命週期。