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

C 語言程序內存佈局全景解析:代碼段、數據段、堆、棧

     編輯:關於C語言

可執行文件與運行時內存映射

靜態映像 (目標文件/可執行文件)


運行時動態增補


關鍵區別:靜態區 (代碼、RO、RW、BSS) 由鏈接器/加載器建立;動態區 (堆、棧) 運行時隨程序行為增長縮減。

各段詳細特徵與對應 C 語言構造

段屬性C 語言對應示例
代碼段只讀、可執行、可共享所有函數機器碼int foo() { return 1; }
RO Data只讀const 全局/靜態、字符串常量const char* s = "hello";
RW Data讀寫、已初始化已初始化全局/靜態變量int g = 10; static int sg = 20;
BSS讀寫、未初始化、運行時清零未初始化全局/靜態變量int arr[1000]; static int cnt;
堆讀寫、手動管理malloc/free/new/deleteint* p = malloc(100);
棧讀寫、自動管理、向下增長局部變量、參數、返回地址void f(int x) { int a; }

關鍵規則與避坑指南

1. const 與存儲段

const char ro[] = "abc";      // RO Data (含內容)
const char* ptr = "abc";      // ptr 在棟/RW/BSS,"abc" 在 RO Data
char* p = "abc";              // 警告!字符串常量不可修改,應用 const char*

2. 靜態變量統一歸屬

  • static 修飾全局/局部變量 → 均存放於 RW Data (已初始化) 或 BSS (未初始化)
  • 區別僅在於可見性:文件級 vs 函數級作用域

3. 棧的三大用途

  1. 函數局部變量 (自動存儲期)
  2. 函數參數傳遞 (值傳遞時複製)
  3. 函數返回地址、保存寄存器 (調用幀)

風險:遞歸過深、大對象值傳遞、大局部陣列 → 棧溢出。

4. 動態分配必須釋放

char* p = malloc(100);
strcpy(p, "data");
free(p);  // 必須配對,否則內存洩漏
// 程序結束時 OS 回收,但長期運行服務必須嚴格管理

實戰內存佈局演示程序

const char ro[] = "read only";           // RO Data
static char rw1[] = "global rw";         // RW Data
char bss1[100];                          // BSS
const char* ptr_const = "constant";      // 字符串在 RO Data

int main() {
    short stack_var;                     // 棧
    char stack_arr[100];                 // 棧
    char stack_str[] = "stack string";   // 棧 (內容從 RO Data 複製)
    
    static char rw2[] = "local rw";      // RW Data (局部靜態)
    static char bss2[100];               // BSS (局部靜態)
    static int c = 0;                    // RW Data
    
    char* heap_ptr = malloc(10);         // 堆
    strcpy(heap_ptr, "heap");            // "heap" 在 RO Data
    free(heap_ptr);
    return 0;
}

段名稱術語釐清

  • Section (節):目標文件中的靜態區域 (ELF/PE 格式)
  • Segment (段):運行時進程虛擬地址空間中的映射區域
  • 多個 Section 可合併為一個 Segment (如 RW Data + BSS 合併為一個可讀寫 Segment)

調試技巧:查看實際地址分佈

printf("ro: %p\n", ro);
printf("rw1: %p\n", rw1);
printf("bss1: %p\n", bss1);
printf("stack_var: %p\n", &stack_var);
printf("heap_ptr: %p\n", heap_ptr);

觀察地址數值大小關係:代碼段 < 數據段 < 堆 < 棧 (典型 Linux x86 佈局)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved