標籤:

C++內存劃分類型?

1.在網上查資料看到:兩種說法,一種是分為 棧,堆,自由存儲區,全局,常量;第二,堆,棧,全局,常量,程序代碼區,到底哪一個是對的呢?我個人一直是理解堆和自由存儲區是一種東西,請解答一下疑惑

2,另外一個問題:類的成員函數,存放在什麼地方呢?

相關問題:C++中如何分配內存? - 編程


第一個問題,如下:

1 .rodata段:存放只讀數據,比如printf語句中的格式字元串和開關語句的跳轉表。也就是你所說的常量區。

例如,全局作用域中的 const int ival = 10,ival存放在.rodata段

再如,函數局部作用域中的printf("Hello world %d
", c);語句中的格式字元串"Hello world %d
",也存放在.rodata段

2 .text段:存放已編譯程序的機器代碼。

注意:程序載入運行時,.rodata段和.text段通常合併到一個Segment(Text Segment)中,操作系統將這個Segment的頁面只讀保護起來,防止意外的改寫。

3 .data段:存放已初始化的全局變數。而局部變數在運行時保存在棧中,既不出現在.data段,也不出現在.bss段中。就是你所說的全局區。

例如:全局作用域中的int ival = 10,static int a = 30,以及局部作用域中的static int b = 30,這3個變數均存放在.data段中。注意,局部作用域中的static變數的生命周期和其餘棧變數的生命周期是不同的。

4 .bss段:存放未初始化的全局變數。在目標文件中這個段不佔據實際的空間,它僅僅是一個佔位符,在載入時這個段用0填充。目標文件區分初始化和未初始化變數是為了空間效率:在目標文件中,未初始化變數不需要佔據任何實際的磁碟空間。全局變數如果不初始化則初值為0,同理可以推斷,static變數(不管是函數里的還是函數外的)如果不初始化則初值也是0,也分配在.bss段。

例如,全局作用域中的int ival; ival顯然存放在.bss段

注意:
.data和.bss在載入時合併到一個Segment(Data Segment)中,這個Segment是可讀可寫的。

5. 棧:函數的參數和局部變數是分配在棧上(但不包括static聲明的變數)。在函數被調用時,棧用來傳遞參數和返回值。由於棧的後進先出特點,所以棧特別方便用來保存/恢復調用現場。

6. 堆:用於存放進程運行中被動態分配的內存段,它的大小並不固定,可動態擴張或縮減。當進程調用malloc/free等函數分配內存時,新分配的內存就被動態添加到堆上(堆被擴張)/釋放的內存從堆中被剔除(堆被縮減)

現在回答你第二個問題,類的成員函數存放在代碼段。

在C++中,如果類中有虛函數,那麼它就會有一個虛函數表的指針__vfptr,在類對象最開始的內存數據中。之後是類中的成員變數的內存數據。注意要考慮對齊。


C++語言標準中沒有堆、棧、自由存儲區、程序代碼區這些東西。

C++並不在意你在哪裡存儲你的對象。它僅僅在意對象的生命期。堆和棧是比較常見的對標準中規定的一些存儲類型的實現,但是標準中沒有規定這樣的實現細節,你就算把對象放到另一台計算機的資料庫或者EPROM裡面,順便在分配對象的時候發射一枚核導彈,只要對象生命期沒問題,也是符合標準的。動態存儲期間的變數所佔用的空間也被稱為自由存儲區。堆、棧、自由存儲區都可以有很多個,比如Visual C++有本地堆和託管堆,都算是自由存儲區。脫離特定的編譯器來談這些編譯器自決的行為沒有意義。

程序代碼區是某些可執行文件格式中規定的。具體採用什麼文件格式取決於編譯器。比如MSDOS的COM文件格式就沒有分段。即使是支持分段文件格式的編譯器,具體把變數和常量放在哪個段,是否將一個函數內聯到調用者等等仍然是編譯器自決的行為。


C/C++內存管理詳解,希望對你有幫助


一樓回答的很專業,學習了。我提供給題主更好的理解方法,其實分成三類就好了:

1、程序結束時釋放的內存類型;

2、程序自動的回收,釋放的內存類型;

3、程序員delete釋放的內存類型。

附:所有的語言都是這樣吧(待考證)。


棧是和硬體底層相關的(使用堆棧指針,一些平台可能稱之為SP),常常用於分配固定大小的內存,例如進入一個C++函數,這時候棧分配了一個內存單元用於返回值或返回值指針,分配一些內存給局部變數。為什麼用棧而不用其他其他內存呢?因為棧的分配只是堆棧指針的偏移,對於C和C++函數來說效率高。【詳見網易公開課《編程範式》】

堆是針對操作系統的,new啊,malloc、delete、free之類的,嵌入式操作系統中new返回的指針常常是不可重複的(除非又delete了)【它常常是操作系統基於某段可用RAM建立的,用戶也可以自己定義】,但是PC的系統一般返回的指針是可以對於不同進程返相同的指針(我也不太懂)。

自由存儲器:不太懂。

全局:對於嵌入式,全局變數總在開機第一時間分配內存。對於PC,常常是操作系統在啟動某個進程的時候才分配的內存。

程序代碼段:常量(如const 或 直接 5 + 3之類的)和代碼常常存於這個地方,在電腦中常存於硬碟,在啟動進程的時候載入常量和代碼到內存(常量也可能一直存於內存,例如早期編譯器沒有優化const的時候,或者const後又使用const_cast等試圖改變其內容)(代碼段也許並不載入到內存中,在嵌入式系統中常常直接運行【因為嵌入式晶元的ROM區常在晶元內,不像硬碟那樣相對RAM那麼慢】)。

函數和類的成員函數一致,只是C++在類的成員函數中省略了一個參數,就是這個對象的指針(所以可以訪問這個對象的成員)。另外,虛函數也會引入一個_vptr虛表指針作為類成員(一個對象一個指針,可以對應指向多個虛函數),也是會保持在非代碼段中(具體看如何創建這個對象,編譯器才能決定放在哪一個內存區域)。


推薦閱讀:

在c++中指針是否能夠被完全替代?甚至是不使用指針?
C++ 是 2012 年不宜進入的技術點嗎?
c++虛函數表在運行時候是如何存在的?
cocos2dx開發遊戲,如果可以使用C++做出來,是不是不用lua,全用C++做更好呢?
C++中this指針藏在哪裡?

TAG:內存管理 | C |