2014-04-28 26 views
7

Wikipedia提到「bss部分通常包括在文件範圍聲明的所有未初始化變量」。鑑於以下文件:確定目標文件上的BSS大小

int uninit; 

int main() { 
    uninit = 1; 
    return 0; 
} 

當我這個編譯爲可執行我看到BSS段正確填寫:

$ gcc prog1.c -o prog1 
$ size prog1 
text  data  bss  dec  hex filename 
1115  552  8 1675  68b prog1 

但是如果我編譯它作爲一個目標文件我沒有看到BSS段(我預計它是4):

$ gcc -c prog1.c 
$ size prog1.o 
text  data  bss  dec  hex filename 
    72   0  0  72  48 prog1.o 

是否有什麼明顯的我失蹤?

我使用的是gcc版本4.8.1。

+0

+1非常好的問題。 –

+0

'void main()'?仍然? – Jens

+0

是的,不知道是什麼驅使我寫這個。固定。 –

回答

5

如果我們用readelf -s看符號表中,我們可以看到:

$ readelf -s prog1.o 

Symbol table '.symtab' contains 10 entries: 
    Num: Value   Size Type Bind Vis  Ndx Name 
    0: 0000000000000000  0 NOTYPE LOCAL DEFAULT UND 
    1: 0000000000000000  0 FILE LOCAL DEFAULT ABS bss.c 
    2: 0000000000000000  0 SECTION LOCAL DEFAULT 1 
    3: 0000000000000000  0 SECTION LOCAL DEFAULT 3 
    4: 0000000000000000  0 SECTION LOCAL DEFAULT 4 
    5: 0000000000000000  0 SECTION LOCAL DEFAULT 6 
    6: 0000000000000000  0 SECTION LOCAL DEFAULT 7 
    7: 0000000000000000  0 SECTION LOCAL DEFAULT 5 
    8: 0000000000000004  4 OBJECT GLOBAL DEFAULT COM uninit  <<<< 
    9: 0000000000000000 16 FUNC GLOBAL DEFAULT 1 main 

我們看到,您uninit符號(「變量」)就是在這個階段,一個「共同」的象徵。它尚未被「分配」給BSS。

見這個問題上「共同」符號的詳細信息:What does "COM" means in the Ndx column of the .symtab section?

一旦最終可執行相連,它將被放置在BSS與您預期。


您可以通過將-fno-common標誌GCC繞過這個問題:

$ gcc -fno-common -c bss.c 
$ size bss.o 
    text data  bss  dec  hex filename 
    72  0  4  76  4c bss.o 

相反,你可能標誌着uninitstatic。這樣,編譯器就會知道沒有其他.o文件可以引用它,所以它不會是一個「通用」符號。相反,它會立即放入BSS,如你預期:

$ cat bss.c 
static int uninit; 

int main() { 
    uninit = 1; 
    return 0; 
} 
$ gcc -c bss.c 
$ size bss.o 
    text data  bss  dec  hex filename 
    72  0  4  76  4c bss.o 
+0

謝謝!這有很大幫助。 –

+0

你的編輯也是相當優秀的筆記。爲什麼stackoverflow真棒:D –

+0

不客氣。對我來說這是一個有趣的練習,因爲我也對你所看到的感到困惑。 –