文字區段(text segment)也稱為程式碼區段(code segment),這裡存放的是可執行的 CPU 指令(instructions)。
這個區段通常位於 heap 或 stack 之後,避免因 heap 或 stack 溢位而覆寫 CPU 指令。
通常文字區段的資料是可以共用的,當多個同樣的程式在執行時,在記憶體中只需要存有一份就夠了,而這個文字區段通常都是唯讀的,避免程式本身誤改了自己的 CPU 指令。
初始化資料區段(initialized data segment)儲存的是一些已經初始化的靜態變數,例如有經過初始化的 C 語言的全域變數(global variables)以及靜態變數(static variables)都是儲存於此處。
這個區段的變數又可分為唯讀區域(read-only area)以及可讀寫區域(read-write area),可讀寫區域用於存放一般變數,其資料會隨著程式的執行而改變,而唯讀區域則是存放固定的常數。
未初始化資料區段(uninitialized data segment)又稱為 bss 區段(這個名稱的起源來自於古老的組譯器,代表 block started by symbol)是儲存尚未被初始化的靜態變數,而這些變數在程式執行之前會被系統初始化為 0 或是 null。
堆疊區段(stack segment)用於儲存函數的區域變數、Value Types (Primitives),以及各種函數呼叫時需要儲存的資訊(例如函數返回的記憶體位址還有呼叫者函數的狀態等),每一次的函數呼叫就會在堆疊區段建立一個 stack frame,儲存該次呼叫的所有變數與狀態,這樣一來同一個函數重複被呼叫時就會有不同的 stack frame,不會互相干擾,遞迴函數就是透過這樣的機制來執行的。
run-time 的 stack frame 包含了:
Stack frame 存活時間是規律可預測的,只存在於 function 的執行期間,一旦 function 執行完畢,系統會自動回收空間,不需要擔心 Memory Leak 在這裡發生。
heap 區段的記憶體空間用於儲存動態配置的變數,例如 C 語言的 malloc 以及 C++ 的 new 所建立的變數都是儲存於此。
堆疊區段一般的狀況會從高記憶體位址往低記憶體位址成長,而 heap 剛好從對面以相反的方向成長。
其存活時間不規律不可預測的,即使已經執行完動態配置的 function ,物件仍可能存在 Heap 中,如malloc後面搭配free來釋放記憶體空間。
system 區段用於儲存一些命令列參數與環境變數,這部分會跟系統有關。
範例
#include <stdio.h>
#include <stdlib.h>
const int global_x = 1; // 儲存於 data 區段(唯讀區域)
int global_y = 1; // 儲存於 data 區段(可讀寫區域)
int global_z; // 儲存於 bss 區段
int main() {
const static int x = 1; // 儲存於 data 區段(唯讀區域)
static int y = 1; // 儲存於 data 區段(可讀寫區域)
static int z; // 儲存於 bss 區段
int w = 1; // 儲存於 stack 區段
// 儲存於 heap 區段
char *buf = (char*) malloc(sizeof(char) * 100);
// ...
free(buf);
return 0;
}
objdump -h "file"
objdump -s "file"
size "file"
幾乎每個 C program 都會用到 printf , Linker 在執行時,都需要將 printf 的 object file 複製到最終的 executable object file 中。 在程式執行時,這些常用函數又會被複製到執行中的 process 的 text 中。 在一個執行數百個程式的系統中,將對記憶體資源造成極大的浪費。