--- tags: C語言 --- # **C 語言程式記憶體配置概念** [**原文**](https://blog.gtwang.org/programming/memory-layout-of-c-program/)  \begin{gather*}C 語言程式記憶體配置\end{gather*} [(LibreOffice 原始檔)](https://blog.gtwang.org/wp-content/uploads/2017/03/memory-layout-of-c-program-diagram-20170301.odg) ## text:程式碼 文字區段(text segment)也稱為程式碼區段(code segment),這裡存放的是可執行的 CPU 指令(instructions)。 這個區段通常位於 heap 或 stack 之後,避免因 heap 或 stack 溢位而覆寫 CPU 指令。 通常文字區段的資料是可以共用的,當多個同樣的程式在執行時,在記憶體中只需要存有一份就夠了,而這個文字區段通常都是唯讀的,避免程式本身誤改了自己的 CPU 指令。 ## data:初始化靜態變數 初始化資料區段(initialized data segment)儲存的是一些已經初始化的靜態變數,例如有經過初始化的 C 語言的全域變數(global variables)以及靜態變數(static variables)都是儲存於此處。 這個區段的變數又可分為唯讀區域(read-only area)以及可讀寫區域(read-write area),可讀寫區域用於存放一般變數,其資料會隨著程式的執行而改變,而唯讀區域則是存放固定的常數。 ## bss:未初始化靜態變數 未初始化資料區段(uninitialized data segment)又稱為 bss 區段(這個名稱的起源來自於古老的組譯器,代表 block started by symbol)是儲存尚未被初始化的靜態變數,而這些變數在程式執行之前會被系統初始化為 0 或是 null。 ## stack(棧):區域變數 堆疊區段(stack segment)用於儲存函數的區域變數、Value Types (Primitives),以及各種函數呼叫時需要儲存的資訊(例如函數返回的記憶體位址還有呼叫者函數的狀態等),每一次的函數呼叫就會在堆疊區段建立一個 stack frame,儲存該次呼叫的所有變數與狀態,這樣一來同一個函數重複被呼叫時就會有不同的 stack frame,不會互相干擾,遞迴函數就是透過這樣的機制來執行的。 run-time 的 stack frame 包含了: * Parameters:函數的參數 * Return address:回傳位址,當function執行完,從哪行code繼續執行 * Local variables:區域變數 Stack frame 存活時間是規律可預測的,只存在於 function 的執行期間,一旦 function 執行完畢,系統會自動回收空間,不需要擔心 Memory Leak 在這裡發生。 ## heap (堆):動態配置變數 heap 區段的記憶體空間用於儲存動態配置的變數,例如 C 語言的 malloc 以及 C++ 的 new 所建立的變數都是儲存於此。 堆疊區段一般的狀況會從高記憶體位址往低記憶體位址成長,而 heap 剛好從對面以相反的方向成長。 其存活時間不規律不可預測的,即使已經執行完動態配置的 function ,物件仍可能存在 Heap 中,如malloc後面搭配free來釋放記憶體空間。 ## system:命令列參數與環境變數 system 區段用於儲存一些命令列參數與環境變數,這部分會跟系統有關。 範例 ```c #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; } ``` ```cmd objdump -h "file" objdump -s "file" size "file" ``` 幾乎每個 C program 都會用到 printf , Linker 在執行時,都需要將 printf 的 object file 複製到最終的 executable object file 中。 在程式執行時,這些常用函數又會被複製到執行中的 process 的 text 中。 在一個執行數百個程式的系統中,將對記憶體資源造成極大的浪費。
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.