c++ new 堆 棧


根據32位的Windows系統默認有2GB的用戶空間,則不能new超過2GB的,執行下列代碼:

double *p = new double[128*1024*1024*2];

會出現下面的錯誤

error C2148: 數組的總大小不得超過 0x7fffffff 字節

也就是說數組的總大小不能超過2GB,但實際上剛好小於2GB也是有問題,執行下列語句會出現下列錯誤

double *p = new double[128*1024*(1024*2 -120)];

debug版本下報如下錯誤

release版本下報如下錯誤

並且release和debug模式下堆棧所能分配最大空間也是有區別,經測試release模式要額外需要120m左右的空間,dubug需要320M的空間,這些空間用於分配程序的代碼段,靜態區,進程和線程的默認堆棧,應該還有一些鏈接庫,debug和release模式的區別可能是鏈接庫的版本不一致,這是自己的理解,不確定對不對。

 

實際上new調的malloc,Windows上malloc調的HeapAlloc,HeapAlloc最后調的VirtualAlloc。
VirtualAlloc只能以比較大的單位(最小4KB)申請內存。HeapAlloc可以申請任意大小的內存。malloc基本上可以視為直接調用HeapAlloc(只是基本上)。new在調用malloc之后,如果是類會調用構造函數。

 

上面說的是堆,下面來說一下棧

每個線程都有一個獨立的棧,默認大小是1M,棧主要用於存儲局部變量和函數參數,例如在某一個函數A里調用另一個函數B,這兩個函數里面的變量是共用一個棧,進入函數B時,B中的參數進行壓棧操作,執行完畢返回時再出棧,這時如果參數內存過大或者遞歸調用過深,就會使壓棧數據超出棧大小,造成棧溢出,在vs的debug模式下是這樣的,但在release模式下分配超出棧大小數據卻不會報錯,並且實際內存也沒有變化,好奇怪。

當然,我們可以修改棧空間的大小,vs中在屬性->鏈接器->系統->堆棧保留大小可以修改,單位是字節,該值為0時表示默認1M的空間。

另外函數堆棧的清理方式決定了當函數調用結束時由調用函數或被調用函數來清理函數幀,在VC中對函數棧的清理方式由兩種:

  參數傳遞順序 誰負責清理參數占用的堆棧
__stdcall 從右到左 被調函數
__cdecl 從右到左 調用者

 

堆和棧的區別

 

1、內存空間

棧:在Windows下,棧是向低地址擴展數據結構,是一塊連續內存區域。這句話意思是棧頂地址和棧最大容量是系統預先規定好,在WINDOWS下,棧大小是2M(也有說是1M,總之是一個編譯時就確定常數),如果申請空間超過棧剩余空間時,將提示overflow。因此,能從棧獲得空間較小。

堆:堆是向高地址擴展數據結構,是不連續內存區域。這是由於系統是用鏈表來存儲空閑內存地址,自然是不連續,而鏈表遍歷方向是由低地址向高地址。堆大小受限於計算機系統中有效虛擬內存。由此可見,堆獲得空間比較靈活,也比較大。

2、分配速度

棧:只要棧剩余空間大於所申請空間,只需要移動棧頂指針就能完成分配,否則將報異常提示棧溢出。
堆:首先應該知道操作系統有一個記錄空閑內存地址鏈表,當系統收到程序申請時,會遍歷該鏈表,尋找第一個空間大於所申請空間堆結點,然后將該結點從空閑結點鏈表中刪除,並將該結點空間分配給程序,另外,對於大多數系統,會在這塊內存空間中首地址處記錄本次分配大小,這樣,代碼中delete語句才能正確釋放本內存空間。另外,由於找到堆結點大小不一定正好等於申請大小,系統會自動將多余那部分重新放入空閑鏈表中。

堆空間開辟需要用系統函數,棧上直接修改指針.

 

內存分配方式有三種:   
   
   1.從靜態存儲區域分配。內存在程序編譯時候就已經分配好,這塊內存在程序整個運行期間都存在。例如全局變量,static變量。   
   
   2.在棧上創建。在執行函數時,函數內局部變量存儲單元都可以在棧上創建,函數執行結束時這些存儲單元自動被釋放。棧內存分配運算內置於處理器指令集中,效率很高,但是分配內存容量有限。   
   
   3.從堆上分配,亦稱動態內存分配。程序在運行時候用malloc或new申請任意多少內存,程序員自己負責在何時用free或delete釋放內存。動態內存生存期由我們決定,使用非常靈活,但問題也最多。

 

參考地址:http://www.cnblogs.com/yyxt/archive/2015/02/02/4268304.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM