2016-08-15 15 views
2

我寫一個簡單的程序,增加了一個值時,一類新的全球集容器(例如:一,二)定義:段故障發生取決於gcc編譯命令中的cpp序列?

GlobalSet.h

#include <set> 
struct GlobalSet{ 
public: 
    static void* addValue(int val); 
private: 
    static std::set<int> s; 
}; 

GlobalSet.cpp

#include "GlobalSet.cpp" 
std::set<int> GlobalSet::s; 
void* GlobalSet::addValue(int val){ 
    s.insert(val); 
    return NULL; 
} 

One.h

struct One{}; 

One.cpp

#include "One.h" 
#include "GlobalSet.h" 
void* globalset =GlobalSet::addValue(1); 

Two.h

struct Two{}; 

Two.cpp

#include "Two.h" 
#include "GlobalSet.h" 
void* globalset2 =GlobalSet::addValue(2); 

TEST.CPP

int main(){ 
return 0; 
} 

但這一計劃將導致段故障依賴於CPP序列GCC編譯命令:

g++ GlobalSet.cpp One.cpp Two.cpp test.cpp -o test.exe //normal 
g++ One.cpp Two.cpp GlobalSet.cpp test.cpp -o test.exe //segment fault!! 

爲什麼會發生?如何解決這個問題,使其無需在意gcc編譯中的cpp序列?

回答

6

歡迎來到Static Initialization Order Fiasco

C++標準不保證多個翻譯單元中全局對象的初始化順序。

根據您的鏈接順序,您的代碼將首先嚐試構造globalset2。但是,這會調用靜態類方法addValue(),該方法嘗試訪問尚未構建的std::set

未定義的行爲和崩潰。

要解決此問題,請轉至www.google.com,搜索「靜態初始化順序失敗」並繼續閱讀,直至您理解問題。一旦你這樣做了,你就會知道該如何解決它,在你的代碼中。