程序編譯內存分布
在C++中,內存分成5個區,他們分別是堆、棧、自由存儲區、全局/靜態存儲區和常量存儲區
1.棧,就是那些由編譯器在需要的時候分配,在不需要的時候自動清楚的變數的存儲區。裡面的變數通常是局部變數、函數參數等。
2.堆,就是那些由new分配的內存塊,他們的釋放編譯器不去管,由我們的應用程序去控制,一般一個new就要對應一個delete。如果程序員沒有釋放掉,那麼在程序結束後,操作系統會自動回收。
3.自由存儲區,就是那些由malloc等分配的內存塊,他和堆是十分相似的,不過它是用free來結束自己的生命的。
4.全局/靜態存儲區,全局變數和靜態變數被分配到同一塊內存中,在以前的C語言中,全局變數又分為初始化的和未初始化的,在C++裡面沒有這個區分了,他們共同佔用同一塊內存區。
5.常量存儲區,這是一塊比較特殊的存儲區,他們裡面存放的是常量,不允許修改(當然,你要通過非正當手段也可以修改)
㈡ 一個程序編譯完成後在內存中是如何存儲的
如上所說,內存被分成 程序代碼區、堆區、棧區 還有個全局數據區
1.程序代碼區:存放你的全部代碼
2.堆區:存放用new 申請的變數(如 int a = new int(5))
3.棧區;存放int = 5;之類的變數(必須放在函數中)
4.全局數據區:存放全局或靜態變數,即定義在函數外的,或加上static的變數
(如:static int a = 5;)
㈢ 問一個較為老的問題,C++程序運行時內存分為幾個區域
一個由C/C++編譯的程序佔用的內存分為以下幾個部分
1、棧區(stack)— 程序運行時由編譯器自動分配,存放函數的參數值,局部變數的值等。其操作方式類似於數據結構中的棧。程序結束時由編譯器自動釋放。
2、堆區(heap) — 在內存開辟另一塊存儲區域。一般由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回收 。注意它與數據結構中的堆是兩回事,分配方式倒是類似於鏈表,呵呵。
3、全局區(靜態區)(static)—編譯器編譯時即分配內存。全局變數和靜態變數的存儲是放在一塊的,初始化的 全局變數和靜態變數在一塊區域, 未初始化的全局變數和未初始化的靜態變數在相鄰的另一塊區域。 - 程序結束後由系統釋放
4、文字常量區 —常量字元串就是放在這里的。 程序結束後由系統釋放
5、程序代碼區—存放函數體的二進制代碼。
㈣ 內存的分配方式有哪幾種
內存的三種分配方式:
1. 從靜態存儲區分配:此時的內存在程序編譯的時候已經分配好,並且在程序的整個運行期間都存在。全局變數,static變數等在此存儲。
2. 在棧區分配:相關代碼執行時創建,執行結束時被自動釋放。局部變數在此存儲。棧內存分配運算內置於處理器的指令集中,效率高,但容量有限。
3. 在堆區分配:動態分配內存。用new/malloc時開辟,delete/free時釋放。生存期由用戶指定,靈活。但有內存泄露等問題。
常見內存錯誤及對策
1. 內存分配未成功,卻被使用。
對策:使用內存之前檢查是否分配成功。用p!=NULL判斷。
2. 內存分配成功,未初始化就被使用。
內存的預設值沒有統一的標准。大部分編譯器以0作為初始值,但不完全是。
對策:內存初始化時賦初值。
3. 內存操作越界。
對策:只能是小心了。
4. 釋放了內存,仍然使用。
(1) 使用顯示delete和free的野指針。
對策:釋放完內存,將指針置為NULL。
(2) 使用隱式delete和free的野指針。主要是指函數返回指向棧內存的指針或引用。
對策:當然是不要返回就可以了。
5. 未釋放內存,導致內存泄露。
用new/malloc開辟了內存,沒用delete/free釋放.
對策:new和delete的個數一定相同;malloc和free的個數一定相同;new[]和[]delete一定對應。
㈤ 編譯時分配內存和運行時分配內存
編譯其實只是一個掃描過程,進行詞法語法檢查,代碼優化而已,編譯程序越好,程序運行的時候越高效。
我想你說的「編譯時分配內存」是指「編譯時賦初值」,它只是形成一個文本,檢查無錯誤,並沒有分配內存空間。
當你運行時,系統才把程序導入內存。一個進程(即運行中的程序)在主要包括以下五個分區:
棧、堆、bss、data、code
代碼(編譯後的二進制代碼)放在code區,代碼中生成的各種變數、常量按不同類型分別存放在其它四個區。系統依照代碼順序執行,然後依照代碼方案改變或調用數據,這就是一個程序的運行過程。
㈥ C語言 + 單片機-內存分布詳解
C語言內存分區示意圖如下:
1. 代碼區
2. 常量區
3. 全局(靜態)區
.bss段
.data段
4. 堆區(heap)
調用函數參數size_t是分配的位元組大小,返回值是一個void型的指針,該指針指向分配空間的首地址。參數是開辟的內存的首地址。
5. 棧區(stack)
在STM32中,內存分配如下:
1. 隨機存儲器—RAM
2. 只讀存儲器—ROM
STM32F103晶元的內部分區如下圖所示。
編譯程序完成後,可以看到編譯後的大小信息,包括Code、RO-data、RW-data和ZI-data的大小。這有助於開發人員和嵌入式系統設計者更好地管理內存資源並確保程序在目標設備上正常運行。
Code:代碼段,指程序由編譯器生成的可執行的機器指令。
RO-data:數據段,指程序中的只讀數據部分,包括常量、字元串、const定義的變數等。
RW-data:數據段,指初始化為「非0值「的可讀寫數據,程序運行的時候這些數據又會常駐在RAM區,應用程序可以修改其內容。包括初始化為非零的全局變數和靜態變數。
ZI-data:數據段,指初始化為0值的可讀可寫數據,它與RW-data的區別是程序剛運行時這些數據初始值全都為0,程序運行時和RW-data的性質一樣,它們也常駐在RAM區,應用程序可以更改其內容。包括未初始化和初始化為零的全局變數和靜態變數。
ZI-data 的棧空間(Stack)及堆空間(Heap):在C語言中,函數內部定義的局部變數屬於棧空間,而使用malloc動態分配的變數屬於堆空間。在程序中的棧空間和堆空間都是屬於ZI-data區域的,這些空間都會被初始值化為0值。
關於哪些數據存儲在Flash區域,哪些數據存儲在SRAM區域,這涉及到程序的存儲狀態。程序具有靜止和運行兩種狀態,靜止態的程序被存儲在非易失存儲器中,如內部FLASH區域。當程序在運行狀態的時候,程序常常需要修改一些暫存數據,這些數據往往存放在Flash中,但需要被復制到RAM中。
程序存儲分布如下圖展示。當程序存儲到晶元的內部FLASH時,它佔用的空間為Code+RO-data+RW-data的總和。程序在執行的時候,需要佔用內部SRAM空間,佔用的空間為RW-data+ZI-data之和。
結論,想要讓一個程序正常運行,必須滿足以下兩個條件:程序編譯後打開工程的map文件,在map文件的最後一段也可以看到ROM的總大小。
劃分依據及好處:首先區分代碼段和數據段。程序源代碼編譯後的機器指令放在代碼段;數據段包括" .data "、" .bss "、" .rodata ",將程序中定義的全局變數和局部變數都稱為數據段。
把程序的「代碼段」和「數據段」分開存放,數據和指令分別被映射到兩個虛擬內存區域,數據段對進程是可讀寫的,而代碼段對進程是只讀的。現代CPU緩存設計成數據緩存和指令緩存分離,程序的指令和數據分開存放提高緩存命中率。
數據段還需要分 ".data"、".bss"、".rodata",主要根據是否占內存空間、讀寫許可權進行區分。".data"段和".bss"段都是可讀寫的數據段,而".rodata"存放的是只讀數據,主要是一些const變數和字元串常量。".rodata"段單獨設立的好處是可以將屬性映射成只讀,減少修改操作,還可以將".rodata"段存放在只讀存儲器中。
全局變數也有細分初始化和未初始化,把全局變數分開存放,初始化為0和未初始化的全局變數放在BSS區,初始化不為0的全局變數存放在數據區。程序有兩個存儲狀態,靜止狀態的程序被存儲在非易失存儲器中,運行狀態的程序需要修改一些暫存數據存放在內存中,減少從ROM讀數據的次數提高效率。