2012-10-09 41 views
5

我正在閱讀O'Reilly的書籍21st Century C,其中作者指出,當與靜態庫鏈接時,「編譯器[有效地]將庫的相關內容複製到最終可執行文件中」。當與靜態庫鏈接時,對象代碼如何被複制到可執行文件中?

我試圖通過創建由該模塊的我自己的靜態庫,以測試這一點:

static char szStr[64]; 

char* single_func() { 
    strcpy(szStr, "Hello string!\r\n"); 
    return szStr; 
} 

void func0() { 
    strcpy(szStr, "Hello"); 
} 

char* func1() { 
    strcat(szStr, " string!\r\n"); 
    return szStr; 
} 

用於測試的創建到c文件,其中一個是調用single_func()和其它呼叫func0()和func1的()。

在這兩種情況下生成的可執行文件都是751290B。如果我直接從模塊中調用strcpy和strcat,那麼這兩個可執行文件最終都是7215B。

這是不是與上述聲明衝突或我缺少關於鏈接的一些細節?

一個相關的問題是靜態庫是1600B,所以這個增加的大小來自哪裏?


附加:

兩個主文件包含的無非調用功能和打印結果,這樣更多:

main0:

#include <stdio.h> 
#include "sharedlib.h" 
int main() { 
    char* szStr = single_func(); 
    printf("%s", szStr); 
    return 0; 
} 

MAIN1:

#include <stdio.h> 
#include "sharedlib.h" 
int main() { 
    char* szStr; 
    func0(); 
    szStr = func1(); 
    printf("%s", szStr); 
    return 0; 
} 

個文件彙編這樣的:

gcc -static main0.c -L. -lsharedlib -o main0 

平臺是Linux和編譯器是gcc v4.6.3。

回答

3

使用靜態庫時,複製單位是庫中的對象文件。既然你的程序都是從目標文件中調用一個函數,那麼這兩個程序都會以可執行文件中的所有目標文件結束,因此結果大小相同(給出或調用調用main()程序的大小)。

可執行文件中的額外信息可能來自多個地方。其中一些將是控制和調試信息。如果你將它靜態地鏈接起來,它可能來自C庫。我們可能需要查看主要計劃和鏈接線,並瞭解該平臺提出通貨膨脹的其他原因。

+1

我已經更新了我的問題,並提供了您詢問的額外信息,但我想我可以開始瞭解這方面的進展情況。 1:當從一個庫的目標文件中使用單個函數時,整個目標文件將被放入可執行文件中。 2:通過使用-static選項_all_庫被捲入最終的可執行文件,產生更大的文件大小。我在這裏糾正? – Kenneth

+1

是的;你在兩個細節上都是對的。如果你看Plauger的書「The Standard C Library」(用於C89標準),你會發現大多數源文件都有一個外部可見的函數,這樣你就不會將沒有使用的文件拖入可執行文件。通過在'-lsharedlib'之後在命令行中添加'-shared',可以大大減少可執行文件的大小。 –

+0

我有點驚訝,C庫正在(似乎是)靜態鏈接。有一段時間(也許是十年前),我認爲C庫不是作爲一個靜態庫提供的(所以它必須被共享)。我可能會誤解,或者它可能在Unix上而不是在Linux上。您可以使用'ldd main0'來檢查正在加載的共享庫。它將列出使用的共享對象。 –

相關問題