在 .NET 執行環境中,垃圾收集器扮演著核心角色,負責自動管理記憶體配置與回收,釋放應用程式不再使用的記憶體資源。回顧 Windows 平台早期的記憶體管理演進,主要經歷過兩種傳統模式:一是完全依賴開發者手動釋放記憶體(如 C/C++),二是採用參考計數機制(如 COM 物件)。這兩種方式雖各有優勢,但也暴露出明顯缺陷。
手動管理模式雖然效能極高,且能精確控制資源釋放時機,但極易導致記憶體洩漏。開發者必須明確告知系統何時不再需要某塊記憶體,一旦疏忽遺漏,洩漏往往在系統資源耗盡、電腦嚴重卡頓時才被發現,除錯難度極大。
參考計數模式雖自動化程度較高,但同樣依賴用戶端正確通知釋放。若有任何用戶端忘記遞減計數,物件將永駐記憶體。更嚴重的是,COM 物件可能獨立於自身進程,系統甚至無法在進程結束時強制回收,比傳統記憶體洩漏更棘手。
.NET 採用標記-壓縮演算法的垃圾收集器。所有動態請求的記憶體均配置在 CLR 維護的受控堆疊上。當受控堆疊滿載需清理時,GC 會啟動並掃描目前程式碼中的所有變數,檢查對堆疊上物件的引用關係,判斷哪些物件可從程式碼觸達(即擁有引用)。無引用物件即視為垃圾,予以刪除並壓縮記憶體空間。此機制與 Java 的 GC 系統異曲同工。
這源於中介語言(IL)的設計規範:
1. 類型安全:任何物件引用皆攜帶足夠資訊以確定物件類型。
2. 引用不可偽造:只能複製現有引用,無法任意構造指標。
這兩點保證了 GC 能精確追蹤所有物件引用關係。反之,C++ 允許指標自由轉換類型,破壞了類型安全,故無法套用 GC 機制。
GC 執行時機不可預測,由 .NET 執行環境根據記憶體壓力自動決定(除非開發者顯式呼叫 GC.Collect())。這意味著物件銷毀時間不確定,釋放非受控資源時需實作 IDisposable 模式搭配 using 區塊,而非依賴完成項。
理解 GC 運作原理,有助於編寫高效能、低延遲的 .NET 應用程式,尤其在大型系統與高併發場景下,合理的物件生命週期管理至關重要。