2016-12-28 83 views
3

我預計:C++與.o和.a文件鏈接:不同的行爲,爲什麼?

用的.o文件鏈接,並鏈接從.o文件將歸檔某文件,應該沒有差別。

但事實並非如此。我有2的源文件,每個文件聲明1class + 1的靜態對象+ 1個功能,以及調用的函數

$cat First.cpp 
#include<stdio.h> 
struct First{ 
    First(){printf("First\n");} 
}; 
void f1(){printf("f1\n");}//Not called in main 
static First f_obj; 

$cat Second.cpp 
#include<stdio.h> 
struct Second{ 
    Second(){printf("Second\n");} 
}; 
void f2(){printf("f2\n");}//Not called in main 
static Second s_obj; 

$cat main.cpp 
void f2(); 
int main() 
{ 
    f2(); 
    return 0; 
} 

$g++ -c First.cpp -fPIC 
$g++ -c Second.cpp -fPIC 
$ar -rvs libmystatic.a First.o Second.o 
$g++ main.cpp -o MylinkSta -lmystatic -L. 
$g++ main.cpp -o MyDirect First.o Second.o 

$./MylinkSta 
Second 
f2 

$./MyDirect 
Second 
First 
f2 

一個main.cpp的所以你可以看到

(1) MylinkSta的運行結果不會構建「第一個」對象,但MyDirect會執行此操作。

(2)雖然'Second'對象總是被構造的。

我真的沒有看到與2'.o'文件鏈接和鏈接'.a'文件與這兩個'.o'文件存檔的任何區別。

他們爲什麼表現不同?我在rhel/ubuntu上用gcc/clang進行了實驗,都顯示了相同的結果。我想知道是否有任何C++ ABI標準說明什麼時候應該真正調用創建的靜態/全局對象,通過任何鏈接選項?

這種差異是如何產生的?

+0

鏈接器只會使用庫中的實際需要的對象文件來滿足某些外部引用;那些沒有以任何方式被引用的被忽略,全局變量和全部。大多數時候你都希望這樣 - 一個大的靜態庫通常包含比給定程序所需要的更多的代碼,你不希望整個事情與你的可執行文件鏈接,所以它最終包含了很多死了,從未使用過的代碼。 –

回答

2

這是由於靜態庫的語義。鏈接器只包含來自靜態庫的文件,前提是它包含某個在命令行之前的目標文件所引用的符號(例如,main.cpp引用了來自Second的f2,因此包含它)。你可以用你周圍的庫覆蓋這種行爲

-Wl,--whole-archive -lmystatic -Wl,--no-whole-archive 

但這不是標準。

+0

賓果,這是我正在尋找的飼料「ld」的選項,它的工作與所有事情明確鏈接。 – Troskyvs

相關問題