1. 程式人生 > >nm命令的學習以及可執行文件中的段

nm命令的學習以及可執行文件中的段

gcc 對數 span 數組聲明 height 減少 std 文本 數據段

今天學習專家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命令的學習以及可執行文件中的段