2010-12-04 65 views
3

是否有全局變量增加可執行文件的大小?如果是的話如何?它是否僅增加數據段大小或文本段大小?全局變量如何影響可執行文件的大小?

如果我有一個全局變量和初始化如下:

char g_glbarr[1024] = {"jhgdasdghaKJSDGksgJKASDGHKDGAJKsdghkajdgaDGKAjdghaJKSDGHAjksdghJKDG"}; 

現在,這是否加1024到數據部分和動初始化字符串的大小爲文本部分?

如果反而爲靜態分配這個數組的空間,如果我malloc它,然後做一個memcpy,只有數據部分的大小會減少或文本部分的大小也會減少?

回答

5

是的,它的確如此。基本上編譯器將它們存儲到數據段。有時如果你在你的代碼中使用一個常量字符數組(如printf("<1024 char array goes here");),它會轉到數據段(AFAIK一些舊的編譯器/ Borland?/可能將它存儲在文本段中)。您可以強制編譯器在自定義節中放置全局變量(對於VC++,它是#pragma data_seg(<segment name>))。

動態內存分配不會影響數據/文本段,因爲它會在堆中分配內存。

2

我不是以專家的身份發言,但我猜想,在程序中簡單地使用那個史詩字符串會增加可執行文件的大小。你使用字符串文字做什麼並不重要,因爲它必須被存儲在的某處

爲什麼它關係到可執行文件的哪個「部分」增加了?這不是一個修辭問題!

+1

字符串**可**被刪除**如果**它實際上並未在任何地方使用。 – 2010-12-04 08:44:15

+0

字符串文字只是一個例子。可能有很多這樣的全局變量,它們可能是結構數組,可能會使用字符串,整數等進行初始化。使用malloc爲這些全局變量分配內存會減小任何大小嗎? – Jay 2010-12-04 08:52:31

1

答案稍微有點實施敏感,但總的來說沒有。您的g_glbarr確實是指向char或指定地址的指針。字符串本身將被放入帶有常量字符串的數據部分,並且g_glbarr將在編譯時成爲字符串地址的符號。您最終不會爲指針分配空間,編譯器只是在鏈接時解析地址。

更新

@Jay,這是八九不離十有點兒相同。整數(通常)只是內聯:編譯器會盡可能地將常量放在代碼中,因爲這是一個常見的情況,大多數常規體系結構都可以直接從直接數據中完成。字符串常量將仍然在某些只讀數據部分。所以,當你做出這樣的:

// warning: I haven't compiled this and wouldn't normally 
// do it quite this way so I'm not positive this is 
// completely grammatical C 
struct X {int a; char * b; } x = { 1, "Hello" } ; 

1變成了「立竿見影」的數據,該"Hello"在只讀數據分配的地方,編譯器將只產生一些分配了一塊可讀寫數據的看起來像

x: 
x.a: WORD 1 
x.b WORD @STR42 

其中STR42是在內存中的串"Hello"的位置的符號名。然後當所有東西都鏈接在一起時,@STR42被內存中字符串的實際虛擬地址替換。

3

答案是實現相關的,但對於穩健的實現,這是它的工作原理與靜態存儲時間(全球或其他方式)的變量:

  • 每當變量初始化,整個初始化值對象將被存儲在可執行文件中。即使只有初始部分被明確初始化(其餘部分隱含爲零),情況也是如此。
  • 如果該變量是常量並且已初始化,它將位於「文本」段或等效項中。有些系統(基於現代ELF,也許Windows也是?)有一個獨立的「rodata」段用於只讀數據,以便將其標記爲不可執行,與程序代碼分開。
  • 非常量初始化變量將位於可執行文件的「數據」段中,該文件在加載程序時由操作系統在寫時複製模式下映射到內存中。
  • 未初始化的變量(根據標準隱式爲零)在可執行文件本身中沒有保留存儲空間,而是在操作系統在程序加載時創建的「bss」段中的大小和偏移量。
  • 這樣的未初始化變量可能被創建在一個單獨的只讀「bss」類段中,如果它們是const限定的。
相關問題