2009-11-26 60 views
22

直到前一段時間,我還以爲.a靜態庫只是一個.o目標文件的集合,只是將它們歸檔並不使它們處理不同。但是與.o對象鏈接並且與包含該.o對象的.a靜態庫鏈接顯然不是相同的。我不明白爲什麼...靜態初始化和銷燬​​靜態庫的全局變量不會發生在g ++中

讓我們考慮下面的源代碼文件:

// main.cpp 
#include <iostream> 
int main(int argc, char* argv[]) { 
    std::cout << "main" << std::endl; 
} 

// object.hpp 
#include <iostream> 
struct Object 
{ 
    Object() { std::cout << "Object constructor called" << std::endl; } 
    ~Object() { std::cout << "Object destructor called" << std::endl; } 
}; 

// object.cpp 
#include "object.hpp" 
static Object gObject; 

讓我們編譯和鏈接運行此代碼:

g++ -Wall object.cpp main.cpp -o main1 
./main1 
> Object constructor called 
> main 
> Object destructor called 

構造函數是全局gObject對象的析構函數被調用。

現在,讓我們在其他程序中創建一個靜態庫從我們的代碼和使用(鏈接):

g++ -Wall -c object.cpp main.cpp 
ar rcs lib.a object.o 
g++ -Wall -o main2 main.o lib.a 
./main2 
> main 
  • GObject的構造函數和析構函數不叫......爲什麼?
  • 如何讓它們自動調用?

謝謝。

回答

29

.a靜態庫包含若干.o但它們沒有鏈接,除非您從主應用程序引用它們。
.o文件獨立鏈接始終。

所以.o鏈接器中的文件總是進入,參考與否,但從.a文件只引用.o目標文件被鏈接。作爲一個說明,靜態全局對象不需要被初始化,直到你實際引用編譯單元中的任何東西,大多數編譯器將在main之前初始化它們,但唯一的要求是它們在任何函數之前被初始化編譯單元被執行。

+2

謝謝。似乎與包含在.a中的所有.o文件的鏈接可以通過使用鏈接器選項-Wl, - 整個存檔(或-Wl,在MacOSX上的-all_load)來強制執行...... – moala 2009-11-26 16:47:49

+1

另請參見-force_load for MacOSX – moala 2009-11-26 17:34:50

+0

如果'some.a'中的'1.o'和'2.o'具有兩個具有相同名稱的全局變量,那麼會出現任何問題嗎?他們可以鏈接到一個可執行文件(考慮情況:全球被引用/不可執行文件)? – 2010-10-02 13:01:12