前言
硬件程序調試比較看重內存的分佈情況,可以通過編譯輸出文件來分析運行時的數據結構
如有疑問,歡迎指正,謝謝
內存分佈圖
- 代碼段 (Text segment):存放程序執行代碼的區域,設計在低地址防止堆棧溢後覆蓋現象,嵌入式系統中也就是ROM區
- 初始化數據段(Initialized data segment):簡稱data段,存放程序中已經初始化全局與初始化靜態變量
- 未始化數據段(Uninitialized data segment):簡稱bss段,存放程序中未初始化全局與未初始化靜態變量,該區域會在程序載入時由內核清零
- 棧(Stack):存放局部變量,自動分配與釋放,函數調用時進行內存的分配,調用結束時進行釋放
- 堆(Heap):動態內存塊,主動分配(malloc/realloc),需要手動釋放(free);可以使用brk和SBR調整大小
代碼論證
1. C源碼樣列
#include <stdio.h>
int main(void)
{
printf("Memory Test!");
return 0;
}
- 使用GCC編譯後,代碼段text佔用97字節,初始化數據段data爲0字節,未初始化數據段bss佔用0字節
2. 代碼上增加不初始化靜態全局變量
#include <stdio.h>
static int a;
int main(void)
{
return 0;
}
- 使用GCC編譯後,未初始化數據段bss增加到4字節,剛好是一個整型變量的佔用空間
3. 增加全局變量並賦初值
#include <stdio.h>
static int a;
int b = 1;
int c = 2;
int main(void)
{
return 0;
}
- 使用GCC編譯後,未初始化數據段bss仍然爲4字節,初始化數據段data爲8字節
4.分析目標文件
#include <stdio.h>
static int a;
int b;
int c = 1;
int d = 2;
const char *str = {"Memory Test1"};
int main(void)
{
int e = 0;
e += 1;
printf("%s",str);
return 0;
}
通過GCC進行編譯,通過objdump指令查看可執行文件
- .text對應的是彙編的指令
- .data數據段對應的就是全局變量c、d,值分別爲1與2
- .rodata段存放了Memory Test1字符串常量
- .bss段未打印,不佔用目標文件
- 上圖中.bss段大小爲4,但是代碼定義了兩個未初始化的變量,這個和編譯器具體實現有關係
結論
- BSS段不保存到目標文件中,所以不佔用目標文件的任何空間
- 數據段保存到目標文件中
- 局部變量在運行時進行創建