2016-04-14 71 views
0

我已經看到很多關於此的問題,但沒有包含關於如何編譯這個特定用例的代碼的解釋。我運行以下命令:g++ main.cpp c.cpp testobj.cpp -o main,但運行這給我一個Segmentation fault (core dumped)。當我在main.cppmain方法中有打印語句並刪除所有TestObj代碼時,它確實起作用。命名空間中的C++全局變量

這是分配C::test常量的正確方法嗎?

main.cpp中:

#include "c.h" 
#include "testobj.h" 

TestObj testobj; 

int main() { 
    return 0; 
} 

c.h:

#ifndef CONSTANTS 
#define CONSTANTS 

#include <string> 

namespace C { 
    extern std::string test; 
} 
#endif 

c.cpp:

#include "c.h" 

namespace C { 
    std::string test = "test"; 
} 

測試obj.h:

#ifndef TESTOBJ 
#define TESTOBJ 

class TestObj { 
public: 
    TestObj(); 
}; 

#endif 

testobj.cpp:

#include "testobj.h" 
#include <iostream> 
#include "c.h" 

TestObj::TestObj() { 
    std::cout << C::test << std::endl; 
} 

回答

2

雖然初始化一個translation unit中的全局變量的順序被很好地定義,翻譯單元之間的順序是

所以如果main.cpp源文件中的testobj對象在C::test對象之前被初始化,那麼你的確會有奇怪的行爲。

如果你有多個翻譯單元,每個翻譯單元都有全局變量,那麼你不能依賴它們之間的初始化順序。

+0

我保存將'TestObj testobj'的聲明更改爲'TestObj * testobj',並通過執行'* testobj = TestObj()'將初始化移動到'main()'方法。 – martijnn2008

+0

@ martijnn2008是的,如果你考慮使用指針安全。 :)所有全局變量初始化後,總是會調用main函數。 –

1

這是由全局靜態變量的初始化順序造成的。它是未定義的,被稱爲static initialization order fiasco。當TestObj::TestObj(使用C::test - 它尚未構建。

解決這個問題的常用方法是全局靜態變量移動到一個函數局部靜態變量,即:

const std::string getTestString() { 
    static std::string test = "test"; 
    return test; 
} 

現在,當你調用getTestString()測試變量將被構建,它會做恰好一次。另外,由於C++ 11中函數中靜態變量的初始化保證是線程安全的。

+0

此外,在靜態變量的構造函數中使用std :: cout是不安全的,因爲std :: cout本身是靜態變量,我們也依賴於它的初始化。 –

+0

@IgorSemenov我沒想過,因爲C++ 11它看起來像是修復了 - http://stackoverflow.com/questions/8784892/is-stdcout-guaranteed-to-be-initialized – marcinj