首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C 語言資料存儲區全景圖:常數區、靜態區、堆疊、堆區的分佈與陷阱

     編輯:關於C語言

四大記憶體區域速覽

區域存放內容生命週期管理方式
常數區 .rodata字串常量、const 修飾的全域變數程式全程唯讀,寫入觸發 SegFault
靜態區 .data/.bss全域變數、static 變數(含區域 static)程式全程編譯期定址,.data 有初值,.bss 零初始化
堆疊區域變數、函數參數、返回位址函數呼叫期間編譯器自動配置/釋放,向下增長
堆區malloc/free/new/delete 動態記憶體手動管理程式員負責,忘釋放造成洩漏

深度解析:常數區的「假常量」陷阱

  • char *p = "hello":p 在堆疊,"hello" 在 .rodata,嘗試 p[0]='H' 會崩潰
  • char a[] = "hello":字串常量作為陣列初始化值,編譯器將字元直接嵌入指令碼區初始化陣列,a 在堆疊,**不佔用常數區**
  • const int g = 10(全域)→ .rodata;const int l = 10(區域)→ 堆疊,仍可透過指標修改(C 與 C++ 行為不同)

靜態區細節:.data vs .bss

  • int g = 5 → .data(映像檔佔空間)
  • int g 或 static int g = 0 → .bss(映像檔僅記錄大小,載入時清零)
  • static 修飾全域 → 僅本檔可見(內部連結);修飾區域 → 僅函數可見,但儲存於靜態區

堆疊分配觀察實驗

int a=0, b=0; int arr[5]={1,2,3,4,5};
printf("%p %p %p", &a, &b, arr);
// &a > &b > arr[0]  先宣告位址較高
// arr[0] < arr[1] < ...  陣列元素位址遞增
// 系統按「最大成員大小」成批配置堆疊空間,造成間隙

段錯誤實戰:寫入常數區

char *p = "readonly"; p[0] = 'w'; // SIGSEGV
const int *q = malloc(4); *q = 5; // OK,指標指向堆區

參考資料

原文出處:淺談 C 語言的資料存儲(一)、(二)

立即數賦值匯編 匯編碼片段 字串常量在 .rodata 指標指向字串常量 ELF 區段分析 陣列初始化不進常數區 陣列初始化匯編 ELF 無字串常量 const 全域變數 匯編對比 .rodata vs .data value0 在 .rodata value1 在 .data 區域 const 仍在堆疊 編譯錯誤:不可修改 const 透過指標修改 const 執行結果:const 被修改 寫入常數區觸發 SegFault SegFault 截圖 static 區域變數累加示範 執行結果:全域累加 加 static 後累加 static 區域變數執行結果
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved