Delphi自動管理的內存
Delphi中原子變量,如Integer、Boolean、Record、枚舉等都是在作用域內編譯器自動申請內存,出了作用域自動釋放;另外,字符串、Variant、動態數組、接口也是由Delphi自動管理。
這些變量都是在棧中存儲的,除了接口。另外,Variant是程序員用函數手工創建的,例如VarArrayCreate;動態數組也是程序員用函數手工創建的,例如SetLength,但這兩種情況都不需要程序員自己釋放。
另外,還有一種變量需要注意,是使用Threadvar聲明的變量,它的作用域是一個線程。這主要用在編寫線程函數時,每一個線程使用一個線程局部存儲。
程序員手工管理的內存
指針和對象是需要程序員手工申請和釋放的內存。
指針包括PChar、Pointer(無類型指針)、記錄指針、變量指針(指向原子變量)、函數指針(例如回調函數,分為全局函數和對象方法)。使用New函數來申請內存,使用Dispose來釋放指針。另外,GetMem、ReallocMem和FreeMem也是一系列申請、釋放內存的函數,可以通過GetMemoryManager和SetMemoryManager函數來讀取和設置Delphi的三個內存管理函數。
對象包括TObject和IUnknown兩顆繼承樹繼承下來的子類對象。必須使用構造方法來構造對象。用構造方法(一般是Create,也可以不是,Delphi的編譯器只認constructor的關鍵字)創建的對象,如果你沒有指定擁有者,那麼必須自己手動釋放,即便是指定了擁有者也需要看實際需要在特定的時刻釋放。釋放一般使用Free方法(IUnknown則不需要手工釋放),更好的方法是使用FreeAndNil(在Sysutils.pas單元),它既釋放占用的內存,同時釋放指針本身。
這些變量都是在堆中存儲的。另外一個需要注意的問題是,TList中的指針都需要程序員自己釋放。
注:
1、 回調函數不屬於內存管理的技術范疇,詳細內容參見《指針》部分。
2、 對象的詳細內容參見《對象模型》部分。
3、 一個指針被多個地方使用,而其中一個地方釋放了,其他地方再使用就會發生異常,這是一個使用指針應該注意的問題。詳細內存參見《指針》部分。
4、 傳遞指針有兩個很明顯的優勢:節省內存、提高速度。詳細內存參見《指針》和《設計技巧》部分。
5、 如何判斷對象和指針是一個技術性很強的主題,csdn上有一些講這個主題的帖子,還可以參見Aimingoo([email protected])寫的一篇名為《關於“如何檢測指針是否是對象”的深入探討》的文章。詳細內存參見《指針》和《對象》部分。