2013-11-02 73 views
1

我正在Visual Studio中執行C++編碼練習,並將此問題顯示爲標題。我知道問題發生在哪裏,但我不知道爲什麼會發生,以及如何解決問題。請幫我解決一下這個。訪問衝突讀取位置0x000000004

class_templete.h

typedef std::string QuestionName; 
class ClassTemplete 
{ 
public: 
    ClassTemplete(Question iQuestionName); 
private 
    static std::map<QuestionName,ClassTemplete *> questionName_questionPointer_map_; 
} 

class_templete.cpp

map<QuestionName, ClassTemplete *> ClassTemplete::questionName_questionPointer_map_; 

ClassTemplete::ClassTemplete(QuestionName iQuestionName) 
{ 
    ClassTemplete::questionName_questionPointer_map_[iQuestionName] = this; 
} 

chapter1_question1.h

class C1Q1 : public ClassTemplete 
{ 
public: 
    C1Q1(QuestionName iQuestionName) : ClassTemplete(iQuestionName) {}; 
private: 
    static QuestionName question_name_; 
    static C1Q1 question_instance_; 
} 

chapter1_question1.cpp

QuestionName C1Q1::question_name_ = "C1Q1"; 
C1Q1 C1Q1::question_instance_(C1Q1::question_name_); 

我發現,問題發生在這個地方,當我運行程序:

ClassTemplete::questionName_questionPointer_map_[iQuestionName] = this; 

但是,我無法解釋爲什麼會發生。

如果需要更多信息,請隨時與我聯繫。

親切的問候,

艾吉

+1

聽起來像'ClassTemplete :: questionName_questionPointer_map_'未初始化,或初始化爲NULL,並在此無效映射上的數組下標引起您嘗試在** 0x000處存儲某些內容... 4 ** –

+0

您嘗試解引用null指針。 –

+0

事實上,我對此的看法越多,這聽起來像是一個在不同翻譯單元(class_templete.cpp)中定義的單例的初始化問題。這不是使用單例的正確方法,包裝它們的訪問器方法是要走的路。 –

回答

5

QuestionName C1Q1:::question_name_相對位於ClassTemplate::questionName_questionPointer_map_?它們似乎都是具有靜態存儲持續時間的變量,即它們是在main()運行之前構建的。然而,C++編譯器/鏈接器僅使用一個翻譯單元(在這種情況下,對象是從上到下構建的)而不是在翻譯單元之間(在這種情況下對象是以隨機順序構造的)來命令構造這種全局對象。

您的問題看起來好像ClassTemplate::questionName_questionPointer_map將在C1Q1::question_name_之後構建。也就是說,當構建C1Q1::question_name_時,正在訪問尚未構建的對象。

傳統的解決方法是使static對象的其他對象依賴一個對象,而是被返回與本地static變量的函數,其參考:

std::map<QuestionName,ClassTemplete *>& 
ClassTemplete::questionName_questionPointer_map_() { 
    static std::map<QuestionName,ClassTemplete *> rc; 
    return rc; 
} 

(請注意,這種結構是不是當你不使用C++ 11時它是線程安全的;它當使用C++ 11時是線程安全的)。

+0

+1,我希望我可以在解決這個問題的時候添加另一個。一如既往,一份出色的工作,先生。 – WhozCraig

+0

@WhozCraig:謝謝。我想,我經常看到這個確切的問題,即我只需要確認相關的標誌(全局對象取決於彼此)。 –

+0

@DietmarKühl當我返回本地靜態變量的引用時,非常感謝您的解決方案。然而,在這種情況下,如果有一種解決方案使用ClassTemplate的靜態變量questionName_questionPointer_map_,我會感到很茫然。如果我使用本地靜態變量,那麼我之前定義的變量就沒有用處了。 :) – jiyi

0

你必須使用std::map::insert,當您插入地圖中的一個新的關鍵,你不能做ClassTemplete::questionName_questionPointer_map_[iQuestionName] = this;

此代碼應工作:

ClassTemplete::questionName_questionPointer_map_.insert(std::make_pair(iQuestionName, this));