第16章 記憶體管理
16.1 記憶體配置方式
記憶體配置方式有以下3種:
一、從“靜態儲存區”分配
例如全域變數,static靜態變數。
二、從“棧”上分配
例如函數內的局部變數(包括形參)。該類運算效率很高,而且一般不存在失敗的危險,但是分配
的記憶體容量有限(2M?),可能會出現堆疊溢位。
三、從“堆(或稱自由儲存區)”上分配
亦稱動態記憶體分配。例如malloc,new等申請的記憶體。該類操作使用靈活,但是較棧上分配開銷大。
一般的原則是:如果使用棧儲存和靜態儲存就能滿足應用要求,那麼就不要使用動態儲存裝置(heap)。
16.2 常見的記憶體錯誤及其對策
1、如果指標p是函數的參數,那麼在函數的入口處用assert(p != NULL); 進行檢查以避免輸入非法參數。
2、確保所有的變數在使用前被初始化。
3、記憶體越界:數組越界。
4、記憶體流失:沒有釋放或釋放不完全。
5、記憶體釋放錯誤: 多次釋放同一塊記憶體。
16.3 指標參數是如何傳遞記憶體的?
編譯器總是要為函數的每個參數製作臨時副本。
16.4 free 和 delete 把指標怎麼啦?
釋放指標指向的記憶體後,一定要將指標置NULL,防止產生“野指標”。
16.5 動態記憶體會被自動釋放嗎?
永遠都不會!
16.6 杜絕“野指標”
16.7 有了malloc()/free()為什麼還要new/delete?
1、malloc()/free()不能自動調用建構函式和解構函式,必須為ADT/UDT類型定義initialize()和destroy()來完成初始化和清除工作。
2、new直接返回目標類型的指標,不需要做顯示的類型轉換了,而malloc()則返回void*,必須做顯示的類型轉換後才能使用。
16.8 malloc()/free()的使用要點
1、函數malloc()的原型如下:
void *malloc(size_t size);
2、函數free()的原型如下:
void free(void *memblock);
16.9 new的3種使用方式
1、plain new/delete
void *operator new(std::size_t) throw(std::bad_alloc);
void operator delete(void *) throw();
2、nothrow new/delete
void *operator new(std::size_t, const std::nothrow_t&) throw();
void operator delete(void *) throw();
3、placement new/delete
void *_operator new(size_t, void *);
void _operator delete(void *, void *);
16.10 new/delete的使用要點
1、new/delete 和 new[]/delete[]必須配對使用。
2、多次delete一個不等於NULL的指標p會導致執行階段錯誤。但是delete一個NULL指標式安全的。
16.11 記憶體耗盡怎麼辦
一個一般性問題:對於32位及以上的作業系統而言,一般情況下使用malloc() 和 new 幾乎不可能導致“記憶體耗盡”。這是因為32位作業系統支援“虛存”,記憶體用完了,自動用硬碟空間頂替。因此,對於32位及以上的應用程式,“記憶體耗盡”的錯誤處理程式幾乎毫無用處。
16.12 用對象類比指標
1、用對象管理記憶體
2、泛型指標 auto_ptr
3、智能指標