2013-11-02 111 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));