2016-12-27 95 views
3

我有2個cpp文件,每個申報1級+ 1個功能+ 1個的靜態對象:相同的C++代碼,不同的鏈接選項導致不同的行爲?

$ cat mya.cpp 
#include<stdio.h> 
struct A{ 
    A(){printf("%s\n",__FUNCTION__);} 
}; 
void fa(){printf("%s\n",__FUNCTION__);} 
static A s_obj; 

$ cat myb.cpp 
#include<stdio.h> 
struct B{ 
    B(){printf("%s\n",__FUNCTION__);} 
}; 
void fb(){printf("%s\n",__FUNCTION__);} 
static B s_obj; 

然後主函數調用 「FB」,而不是 「發」。

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

我試圖編譯並以不同的方式鏈接這些文件:

g++ -c mya.cpp -fPIC 
g++ -c myb.cpp -fPIC 
ar -rvs libmya.a mya.o 
ar -rvs libmyb.a myb.o 
ar -rvs libmystatic.a mya.o myb.o 
g++ --shared -o libmyshare.so mya.o myb.o 
g++ --shared -o libadyn.so mya.o 
g++ --shared -o libbdyn.so myb.o 
g++ nm.cpp -o use1StaticLib -lmystatic -L. 
g++ nm.cpp -o use2StaticLib -lmyb -lmya -L. 
g++ nm.cpp -o use1DynamicLib -lmyshare -L. 
g++ nm.cpp -o use2DynamicLib -ladyn -lbdyn -L. 
g++ nm.cpp -o useDirect mya.cpp myb.cpp 

然後我發現了5個可執行文件有不同的行爲:

$ ./useDirect 
A 
B 
fb 

$ ./use1DynamicLib 
A 
B 
fb 

$ ./use2DynamicLib 
B 
fb 

$ ./use1StaticLib 
A 
B 
fb 

$ ./use2StaticLib 
B 
fb 

相同的代碼,不同的行爲,如何我可不會感到困惑嗎?

我似乎找到了一些線索,只要將mya.cpp和myb.cpp打包到不同的.a/.so文件中,則「A s_obj」不會被構建。爲什麼? A的構造函數有副作用,我沒有指定任何-O優化。

如果原因是「A s_obj」是一個未使用的對象,所以沒有鏈接,那麼,「B s_obj」既不被主函數使用,它爲什麼總是被構造?

需要聽取專家的解釋!

+0

全局構造函數不被依賴,但你已經知道了。這只是未定義的,可能是因爲涉及語言和操作系統規則。 – Jojje

回答

2

我覺得這裏有2種效果,需要加以區分

首先,當您對外部庫的調用,動態連接器是懶惰的,並且實際上叫做只會加載庫。但它會加載整個圖書館。與use2StaticLib,你只使用lib b,所以它只會加載這一個。這同樣適用於use2DynamicLib

二,寫這個:

g++ --shared -o libmyshare.so mya.o myb.o

是一樣的使用

g++ --shared -o libmyshare.so myfile.o

其中MYFILE.CPP是mya.cpp串聯和myb.cpp你是隻是將兩個對象文件複製到一個較大的文件中libmyshare.so,這就是爲什麼當你調用的一個函數時文件,應用程序加載整個libmyshare.so庫。在這種情況下,調用A和B的構造函數來啓動靜態對象。這不會改變libmyshare.so的編譯是靜態的還是動態的。

在任何這些場景中,libA和libB的代碼都包含在您的應用程序代碼中(即使在靜態編譯時),並且所有庫都通過動態鏈接調用。

希望得到這個幫助!

相關問題