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

Delphi 內存管理全景圖:自動 vs 手動、棧 vs 堆、生命週期最佳實踐

     編輯:Delphi

核心認知:Delphi 內存管理是「分類管理」

Delphi 不採用全自動 GC,而是按類型語義劃分:值類型/托管類型自動管理,指針/對象手動管理。理解這條分界線,是寫出無洩漏、無野指針代碼的前提。

第一類:編譯器全自動管理(棧/內聯存儲)

第二類:編譯器托管的引用類型(堆分配,自動引用計數/複製語義)

類型例子存儲位置生命週期規則
原子標量Integer, Boolean, Char, Enum, Float棧 (Stack)作用域結束自動彈棧釋放
靜態記錄record (無托管字段)棧/內聯同作用域自動釋放
靜態陣列array[0..9] of Integer棧/內聯同作用域自動釋放
集合/子範圍set of, 1..100棧同作用域自動釋放

關鍵細節

  • 字串/動態陣列不是對象:無構造函數,SetLength 是運行時函數而非方法。
  • Threadvar 變量:每線程一份獨立副本,線程結束時自動清理,適用於線程局部存儲 (TLS)。
  • 循環引用風險:介面引用計數無法處理循環引用(A→B→A),需手動打斷或用弱引用模式。

第三類:開發者完全手動管理(堆分配,無自動機制)

1. 非類型指針與類型指針

類型內存模型管理機制開發者責任
AnsiString / UnicodeString堆上字符緩衝區 + 引用計數COW (Copy-on-Write) + 歸零釋放無需手動釋放,賦值即複製引用
動態陣列堆上數據塊 + 引用計數SetLength 擴容,歸零釋放SetLength(0) 或 nil 賦值釋放
Variant堆上 TVarData + 可能的字串/陣列/介面內部引用計數VarClear 釋放,賦值自動管理
介面堆上對象 + _AddRef/_ReleaseCOM 引用計數賦值自動增減引用,離開作用域自動釋放

自定義內存管理器:GetMemoryManager/SetMemoryManager 可替換底層分配器(如 FastMM4、ShareMem、針對性調試器)。

2. 對象:TObject 分支與 IUnknown 分支

API用途配對釋放
GetMem/ReallocMem/FreeMem原始字節塊,最靈活FreeMem
New/Dispose帶類型指針,調用構造/析構Dispose
AllocMemGetMem + 零初始化FreeMem

關鍵規則:Owner 機制

  • Create(AOwner):指定 Owner → Owner 銷毀時自動 Free 所有擁有的組件。
  • Create(nil):無 Owner → 必須手動 Free,否則洩漏。
  • FreeAndNil(Obj):SysUtils 提供,釋放後置 nil,防雙重釋放/野指針,強烈推薦。

特殊容器:TList 指針陷阱

TList 只存指針,不知曉指針指向什麼,銷毀時不會釋放指針指向的內存/對象。必須手動遍歷釋放:

for i := 0 to List.Count - 1 do
  TObject(List[i]).Free; // 或 FreeMem 視具體類型
List.Free;

現代代碼請改用 TObjectList<T> (OwnsObjects=True) 或 TList<T> 配合自定義釋放邏輯。

內存管理決策流程圖(文字版)

需要存儲數據
   │
   ├─ 是固定大小、無引用語義? → 用 Record/Static Array/標量 → 自動管理
   │
   ├─ 是可變長文本/字節/集合? → 用 String/Dynamic Array/Bytes → 托管自動
   │
   ├─ 需跨模塊/進程共享、多態換裝? → 用 Interface → 引用計數自動
   │
   ├─ 需要繼承、虛方法、事件、VCL 树? → 用 TObject 類 → 手動 Free / Owner
   │
   └─ 需要原始內存塊、C API 互操作、極致性能? → 用 Pointer/GetMem → 手動 FreeMem

五大避坑鐵律

  1. 誰分配誰釋放:函數返回指針/對象,文檔必須註明調用方負責釋放。
  2. 釋放即置 nil:統一用 FreeAndNil,消滅野指針。
  3. 異常安全:try..finally 保護所有手動資源,或用介面/記錄包裝 RAII。
  4. Owner 鏈清晰:UI 控件必須有 Owner (Form/Frame),非 UI 業務對象明確文檔所有權。
  5. 工具輔助:FastMM4 FullDebugMode、ReportMemoryLeaksOnShutdown := True、CodeGuard、LeakCheck 開啟調試構建檢測洩漏。

總結

Delphi 內存管理不是「全自動」也不是「全手動」,而是分層語義化:值類型/托管類型交給編譯器,指針/對象交給開發者(輔以 Owner 機制)。內記「棧上自動、堆上托管、對象手動、Owner 托底」,外用 FreeAndNil + FastMM4 調試,即可在無 GC 語言中寫出穩健、高性能、無洩漏的系統級應用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
分支根類創建釋放適用場景
VCL/傳統TObjectConstructor (通常 Create)Free / FreeAndNilUI 控件、業務對象、數據模塊
COM/介面TInterfacedObjectConstructor介面變量離開作用域自動 _Release插件、跨模塊、需引用計數場景