2012-08-13 72 views
2

我在匿名命名空間中有一個全局變量。cpp文件中的全局變量

namespace { 
std::unordered_map<std::string, std::string> m; 
} 


A::A() { m.insert(make_pair("1", "2")); } // crasches 
void A::insert() { m.insert(make_pair("1", "2")); } // ok 

如果嘗試使用map在構造函數中,我得到訪問衝突閱讀位置。 但是,如果我使用它A已經初始化它的作品。
這種行爲是否正確?

+1

我們需要更多的代碼。 – 2012-08-13 13:28:35

+0

你有靜態成員'A'嗎? – 2012-08-13 13:30:18

+1

如果在另一個cpp文件中定義了全局實例,則此實例和m的創建順序未定義。 – 2012-08-13 13:31:50

回答

8

構造函數調用導致崩潰的A對象的作用域是什麼?

有沒有保證,而靜態初始化被執行,訂單因此,如果您A對象也是一個全球性的或靜態的(如m是),它很可能是m不會被一個條件還不存在有效構造的對象,這意味着您對std::unordered_map::insert()的調用將在未初始化的內存上調用,從而導致您的崩潰。

解決方案是確保所有依賴於mA實例都由您明確構建,而不是靜態/全局構建(或者添加了評論者,如果他們位於相同的TU中,則可以對其進行正確排序) ,或者更改A的結構,以便稍後可以調用實例的函數以執行插入操作。這是否是一個有效的解決方案更多地取決於A的總體用途。

+0

一個更正:翻譯單位**沒有這樣的保證**。在一個翻譯單元中,它們按照聲明的順序進行初始化。 – atzz 2012-08-13 13:33:24

+0

另外還有一點:最好的辦法是避免靜態對象初始化之間的依賴關係;但如果無法完成 - 請使用create-on-access單例而不是純靜態變量。 – atzz 2012-08-13 13:35:18

+0

如果**用戶的描述是正確的(但我認爲我們錯過了一篇文章並且您已經猜到了),這不太可能是問題**。由於它位於匿名名稱空間中,因此它已經位於同一個翻譯單元中(因爲匿名名稱空間對象受此限制)。上面代碼的顯示方式顯示'm'要在任何A之前聲明(儘管還有許多想象力)。所以初始化的順序不應該是一個問題(如果它是一個簡單的全局重排序應該可以解決問題)。 – 2012-08-13 13:49:34

2

您可能在您的應用程序中的某個地方,即在執行main()函數之前,因此在初始化m之前,在靜態上下文中創建類型爲A的類。