nm命令的學習以及可執行文件中的段
今天學習專家c的運行時數據結構,順便簡單地學習了一下nm命令
就目標文件而言,段是二進制文件中的簡單區域裏面保存了一定信息,section是ELF文件中最小組織單元,一個段包含幾個section.
nm命令的作用是顯示對象文件,可執行文件以及對象文件庫的符號信息.這裏只對可執行文件的符號信息進行研究.
以hello world 程序為例
#include <stdio.h> int lemon[1000]; int main(){ printf("Hello World!\n"); return 0; }
/*test.c*/
用gcc test.c 命令編譯後默認生成 a.out 這個默認名字的文件是由鏈接器產生的,之所以叫a.out是因為在遙遠的過去,也就是鏈接器還沒有被發明時,匯編產生的程序
就保存在這個a.out文件中(assembler output的縮寫),發明鏈接器後由鏈接器產生的文件仍然保留了這個稱呼.
生成的a.out文件我們先來看看它的大小 即 ls -l a.out 以及它的各個端的大小即 size a.out
再來用nm 命令來看看符號信息 這裏用了 -S 選項和 -t FORMAT 選項來方便顯示. -S選項是打印定義了的符號的大小的開關. -t FORMAT 是以十進制,十六進制
八進制來打印數字的開關.
觀察一下得到的結果第一列為該符號的地址,第三列可能為該符號的大小,可以看到lemon的大小就是4000字節,最後一列為符號的名字
我們來看看第二列有大小的T,t,大小寫的B,b等等
這裏的大寫為GLOBAL小寫為LOCAL
b(B)為BSS
d(D)為DATA
t(T)為TEXT
U表示該符號在該文件中是未定義的,即在其他的文件中定義
再來看看當該數組賦值時的情況
文件的大小增加了大約4000字節
而看看可執行的文件中的段,data段大概增加了4000字節,bss段減少了大約4000字節,段總大小幾乎不變
所以可以得出結論bss段並不占用可執行文件的任何空間,只是記錄其大小.
再來看看把數組聲明在函數中會怎樣
文件的size比以前少了大約4000字節,段的總的大小也少了4000字節左右
利用nm命令看看
可以發現可執行文件已經沒有lemon這個符號了,當對數組進行初始化後也一樣.可見在函數中聲明的數組並沒有存在段中.
最後看看調試選項對可執行文件的影響
可見調試編譯對可執行文件大小有影響,但對段的大小並沒有影響
總結:
數據段保存在可執行文件中
bss段不保存在可執行文件中
a.out文件大小受調試狀態編譯的影響,而段不受影響
疑惑:
為什麽說文本段是最易受優化措施影響的段.
(看完這章後來試試解決這個疑問)
nm命令的學習以及可執行文件中的段