目錄
- 內存分區
- 代碼運行前后區別
- 各分區詳細解釋
- C++內存申請和釋放
內存分區
不同的操作系統對程序內存的管理和劃分會有所不同。
此處是C++內存區域劃分主要是針對通用的情況,并不限定在某個特定操作系統上
一般分為4個區(有時把全局區拆分成數據區+未初始化數據區,就是五個區)
代碼區:存放CPU 可執行的機器指令
全局區(靜態區):存放全局變量,靜態變量,常量(又分為數據區+未初始化數據區)
堆:程序員自己管理申請和釋放的內存
棧:編譯器管理申請和釋放的內存,一般是函數形參,局部變量
代碼運行前后區別
運行前
程序源代碼被編譯之后主要分成兩種段:程序指令(代碼區)和程序數據(數據區)。代碼段屬于程序指令,而數據域段和 bss 段屬于程序數據。
在沒有運行程序前(程序沒有加載到內存前),內存分為代碼區(text)、數據區(data)和未初始化數據區(bss)3 個部分(把 data 和 bss 合起來叫做靜態區或全局區)。
運行后
運行后內存分為5個區:代碼區+數據區+未初始化數據區+棧區+堆區
程序在加載到內存前,代碼區和全局區(data+ bss)的大小就是固定的,程序運行期間不能改變。然后,運行可執行程序,操作系統把物理硬盤程序加載到內存,除了根據可執行程序的信息分出代碼區(text)、數據區(data)和未初始化數據區(bss)之外,還額外增加了棧區、堆區。
各分區詳細解釋
代碼區(text段)
代碼區通常是可“共享”的,可以被多個程序調用,這樣有利于節省內存,對于需要頻繁被執行的程序,只需要在內存中有一份即可
代碼區是只讀的,防止程序意外的修改了它的指令。另外,代碼區還規劃了局部變量的相關信息。
程序運行時,內存的代碼區加載的是可執行文件代碼段,所有的可執行代碼都加載到代碼區,這塊內存是不可以在運行期間修改的。
數據區(又叫全局初始化數據區/靜態數據區)(data段)
包含被初始化的全局變量、已初始化的靜態變量(包括全局靜態變量)和常量數據(如字符串常量)。
程序運行時,加載的是可執行文件數據段,存儲于數據段(全局初始化,靜態初始化數據,文字常量(只讀))的數據生存周期是整個程序運行過程。
未初始化數據區(又叫 bss 段)
存入的是全局未初始化靜態變量。未初始化數據區的數據在程序開始執行之前被內核初始化為 0 或者空(NULL)。
程序運行時,加載的是可執行文件 BSS 段,位置可以分開也可以緊靠數據段,存儲于數據段的數據(全局未初始化,靜態未初始化數據)生存周期是整個程序運行過程。
棧區(stack)
程序運行后才被分配堆棧區
棧是由編譯器自動分配釋放,存放函數的參數值、返回值、局部變量等。在程序運行過程中實時加載和釋放,因此,局部變量的生存周期為申請到釋放該段棧空間。
堆區(heap)
程序運行后才被分配堆棧區
堆是一個大容器,它的容量要遠遠大于棧,但沒有棧那樣先進后出的順序。用于動態內存分配。堆在內存中位于 BSS 區和棧區之間。一般由程序員分配和釋放,若程序員不釋放,程序結束時可能會由操作系統回收。
補充:為什么把程序的指令和程序數據分開呢?
程序被加載到內存中之后,可以將數據和代碼分別映射到兩個內存區域。由于數據區域對進程來說是可讀可寫的,而指令區域對程序來講是只讀的,所以分區之后呢,可以將程序指令區域和數據區域分別設置成只讀或可讀可寫。這樣可以防止程序的指令有意或者無意被修改。
當系統中運行著多個同樣的程序的時候,這些程序執行的指令都是一樣的,所以只需要內存中保存一份程序的指令就可以了,只是每一個程序運行中數據不一樣而已,這樣可以節省大量的內存。
C++內存申請和釋放
//申請內存
int* a = new int(10);//申請一片內存存放int型數據10
int* arr = new int[10];//申請一個長度為10的int型數組//釋放內存
delete a;
delete[] arr;//釋放數組