2013-01-15 70 views
2

我現在正在閱讀本書的第6章專家C編程並對數據段的大小非常好奇。Mac OS可執行文件的DATA段是什麼?

我寫了3個程序來查看數據段的區別。

我的平臺是MacBook Pro,OS X 10.8,我使用命令clang xxx.c來編譯代碼。

int main() 
{ 
    int i, j; 
    return 0; 
} 

__TEXT 4096 __DATA 0


int arr[10000]; 
int main() 
{ 
    int i, j; 
    return 0; 
} 

__TEXT 4096 __DATA 40960


int main() 
{ 
    int i, j; 
    int arr[10000]; 
    return 0; 
} 

__TEXT 4096 __DATA 4096

爲什麼這三種尺寸都不相同?

回答

0

在第二個示例中,數組是靜態初始化的,即它存在於整個生命週期中。鏈接器在數據部分中保留10000個整數的空間。

在第三個實例中,陣列獲取main()函數的堆棧上創建,即它起初存在,並且只有被初始化該過程進入main()後(這是相同作爲「流程的整個生命週期」,因爲運行支持代碼在main()之前運行,並且清理運行在它之後的東西)。鏈接器爲數據部分保留空間(我不太確定是什麼),其餘部分(4096減去保留的項目的大小)是頁面對齊的部分的效果(即,分配給頁面的倍數大小,在這種情況下4k)。

+0

你的第二段的最後兩句是完全錯誤的。 *堆棧上的緩衝區*未初始化*。即使它被置零,它也會使用(硬編碼)指令立即值,而不是數據部分中的零。 –

+0

@JonathonReinhart:再想一想,你很可能是對的。我不得不承認,我對第三個例子的數據部分沒有把握,但大小(4096)絕對是頁面對齊效果。 – DevSolar

1

文本部分是程序文本(或代碼)的存在位置。所以這是有道理的,它會在你的三個例子中不變。

在第一個,你沒有全局變量,沒有字符串文字等,所以數據大小爲零。

在你的第二個例子,你有一個〜40K的全局緩衝區,它出現在數據部分(實際上可能是BSS,因爲它是未初始化的,因而不會在執行一起去。)

在第三個示例中,緩衝區位於的stack上。儘管您並未添加任何全局數據,但我不太確定它的數據大小爲何不爲零。

很多可執行格式都會將這些區段大小對齊,以便於系統執行。英特爾x86頁面大小爲4KiB,這就是爲什麼我懷疑鏈接器將這些部分對齊到4096.

4

除非您正在編寫程序加載程序或者在嵌入式系統上工作,否則真的不需要關心不同的細分。

但是,三經典標準段是:

  • 文本,其中包含實際可執行代碼
  • 數據,其包含初始化的數據(例如初始化的全局變量)
  • 和其中包含未初始化的數據(例如未初始化的全局變量)

本地內部函數的變量在運行時放置在堆棧上,因此沒有特定的段。

這些段通常是多個平臺頁面大小,其在i386和派生詞上是4096字節。因此,即使只需要一個字節,分段大小也會四捨五入爲4096字節。在你的第二個例子中,你有40000字節的數據,它被四捨五入爲4096的最接近倍數40960.

如果有一個段,其中的數據通常被程序加載器歸零。關於段的另一個注意事項是,它實際上並沒有在對象或可執行文件中使用任何空間。由於其數據未初始化,因此不需要在內存中存儲除大小以外的任何內容。

+0

如何查看數據段的內容? 我用過'''otool -d a.out''',但輸出是'''a.out'''。 – Jiajun

+0

@Jiajun ['otool'](http://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/otool.1.html)似乎是正確的命令。對於哪個例子,你會得到'a.out'輸出?也許這是數據部分唯一的事情? –

+0

對於所有這三個,但命令'''otool -t a.out'''幫助。 – Jiajun

相關問題