關于C/C++內(nèi)存管理示例詳解
1、內(nèi)存分配方式
在C++中,內(nèi)存分成五個區(qū),分別是堆、棧、自由存儲區(qū)、靜態(tài)存儲區(qū)和常量存儲區(qū)。
1) 棧
執(zhí)行函數(shù)時,函數(shù)內(nèi)局部變量的存儲單元都可以在棧上創(chuàng)建,函數(shù)執(zhí)行結束時這些存儲單元自動被釋放。棧內(nèi)存分配運算內(nèi)置處理器指令集中,效率很高,但分配的內(nèi)存容量有限。
2) 堆
由new分配的內(nèi)存塊,釋放由程序員控制。如果程序員沒有釋放,那么就在程序結束的時候,被操作系統(tǒng)回收。
3) 自由存儲區(qū)
由malloc等分配的內(nèi)存塊,用free結束自己的生命。
4) 靜態(tài)存儲區(qū)
全局變量和靜態(tài)變量被分配到同一塊內(nèi)存中。C語言中,全局變量分為已初始化和未初始化。
5) 常量存儲區(qū)
里面存放的是常量,不允許修改。
2、堆和棧的區(qū)別
int * ptr = (int*)malloc(sizeof(int)*4);
在棧中存放了一個指向堆內(nèi)存的指針ptr。在程序會先確定在堆中分配內(nèi)存的大小,然后利用operator new分配內(nèi)存,然后放回這塊內(nèi)存的首地址,放在棧中。
1) 空間大小不同
在32位系統(tǒng)中,堆的空間是4G,而棧的空間很小。
2) 分配方式不同
堆是動態(tài)分配的,沒有靜態(tài)分配。棧的靜態(tài)分配時編譯器完成的,動態(tài)分配由alloca函數(shù)分配。棧的動態(tài)分配由編譯器進行釋放。
3) 管理方式不同
棧是由編譯器自動管理。堆的釋放是由程序員控制。
4) 生長方式不同
堆的生長方式是向上的,向著內(nèi)存地址增加的方向。棧的生長方式是向下的,是向著內(nèi)存地址減小的方向。
5) 能否產(chǎn)生碎片
對于堆,頻繁的new/delete會造成內(nèi)存空間的不連續(xù),從而造成大量的碎片,使程序效率降低。
6) 分配效率不同
棧是機器系統(tǒng)系統(tǒng)的數(shù)據(jù)結構,計算機會在底層對棧提供支持:分配專門的寄存器存放棧的地址,壓棧出棧都有專門的指令執(zhí)行,這就決定棧的效率比較高。
堆是C/C++函數(shù)庫提供的,庫函數(shù)會按照一定的算法,在堆內(nèi)存中搜索可用的足夠大小的空間,如果沒有足夠大小的空間(可能是由于內(nèi)存碎片太多),就有可能調用系統(tǒng)功能去增加程序數(shù)據(jù)段的內(nèi)存空間,這樣就有機會分到足夠大小的內(nèi)存,然后進行返回。
3、operator new和operator delete
3.1 為什么要進行重載?
在嵌入式系統(tǒng)中,由于內(nèi)存的限制,頻繁的動態(tài)分配不定大小的內(nèi)存會引起很大的問題以及堆破碎的風險。
當你必須要使用new和delete的時候,你不得不控制C++中的內(nèi)存分配。你需要用重載的全局new和delete代替系統(tǒng)的內(nèi)存分配符。需要給類重載new和delete。
一個防止內(nèi)存破碎的方法是從不同固定大小的內(nèi)存池中分配不同類型的對象。對單個類重載new和delete,你就可以靈活的控制內(nèi)存分配。
3.2 重載全局的new和delete操作符
void* operator new(size_t size) { void* p = malloc(size); return (p); } void operator delete(void*p) { free(p); }
3.3 類重載new和delete
為單個類重載new和delete
class TestClass { public: void* operator new(size_t size) { void* p = malloc(size); return p; } void operator delete(void* p) { free(p); } };
為單個類重載new[] 和 delete[]
class TestClass { public: void* operator new[](size_t size) { void* p = malloc(size); return p; } void* operator delete[](void* p) { free(p); } } int main() { TestClass* p = new TestClass[10]; delete [] p; return 0; }
注意:new[] 中的個數(shù)參數(shù)是數(shù)組的大小加上額外的存儲對象數(shù)目的字節(jié)??紤]到內(nèi)存分配機制的因素,盡量避免使用對象數(shù)組。
4、有了malloc/free為什么還要new/delete
malloc和free是C/C++語言的標準庫函數(shù),new / delete是C++ 的運算符。都用于申請動態(tài)內(nèi)存和釋放內(nèi)存。
malloc / free 無法滿足動態(tài)對象的要求。對象在創(chuàng)建的同時同時自動執(zhí)行構造函數(shù),對象消亡之前自動執(zhí)行析構函數(shù)。即就是C++語言需要一個能完成動態(tài)內(nèi)存分配和初始化工作的運算符new,以及一個能完成清理和釋放內(nèi)存工作的運算符delete。
內(nèi)部數(shù)據(jù)類型的對象沒有析構和構造的過程,所以對于他們來說malloc / free和new / delete是等價的。
5、內(nèi)存耗盡的三種解決方法
在申請動態(tài)內(nèi)存時,找不到足夠大的內(nèi)存塊,malloc和new將返回NULL指針。
1)判斷指針是否為NULL,如果是則使用 return 終止函數(shù)
2)判斷指針是否為NULL,如果是則使用 exit(1) 終止程序
3)為malloc和new 設置異常處理函數(shù) 。
總結
到此這篇關于C/C++內(nèi)存管理的文章就介紹到這了,更多相關C/C++內(nèi)存管理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java C++ 題解leetcode1619刪除某些元素后數(shù)組均值
這篇文章主要為大家介紹了Java C++ 題解leetcode1619刪除某些元素后數(shù)組均值示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-09-09