C ++ STL映射异常。 (不可变树的根)

时间:2014-02-10 10:14:17

标签: c++ map stl c++builder

我的参数类有问题。当我尝试以除main之外的任何其他形式调用getProperty时,我得到异常"访问冲突在0x00459bd6:读取地址0x00000030"在xtree上这段代码

_Nodeptr& _Root() const
    {   // return root of nonmutable tree
    return (_Parent(_Myhead));
    }

通过此代码以主窗体初始化的类

 parameters = Parameters::getInstance();

参数类代码:

template <typename T>
class Singleton
{
public:
    virtual ~Singleton () {};
    static T* getInstance ()
    {
        if (!singletonInstance)
        {
            singletonInstance = new T ();
        }
        return singletonInstance;
    }

protected:
    Singleton () {};
    static T* singletonInstance;
};

template <typename T>
T* Singleton<T>::singletonInstance;

class Parameter
{
public:
    string value;
    string maxValue;
    string minValue;
    string type;

    Parameter();
    Parameter(string val);

    Parameter& Parameter::operator=(Parameter& p);
};

typedef map<string, Parameter> InnerMap;
typedef map<string, InnerMap> MainMap;

class Parameters : public Singleton <Parameters>
{
private:
    MainMap params;

    void loadParametersList(string filename);

    Parameters() : Singleton<Parameters>()
    {
        loadParametersList("parameters.lst");
    }

protected:
    friend class Singleton<Parameters>;

public:
    string getProperty (string category, string name);

    void loadParametersFromIni(string filepath);
    void saveParametersToIni(string filepath);
};

Parameters *parameters;

UPD.1 我在stacktrace上的最后一个函数是getProperty。这是getProperty的代码:

template <>
std::string Parameters::getProperty (string category, string name)
{
    return params[category][name].value;
}

此代码在主窗体中工作正常,但以任何其他形式/

调用异常

如果您有一点时间,我可以提供一个小程序来说明电子邮件中的问题。

1 个答案:

答案 0 :(得分:1)

看起来在Parameters类头文件中声明全局使用的参数指针会导致范围问题。可以这样想,每当包含最后一行的头文件带入#include时,就会声明并创建另一个指针实例。声明参数头文件底部的参数指针实例将每次都这样做。但很多时候,带有

的Parameters.h
#include "Parameters.h" 

另一个独立参数指针未设置为任何有意义的内存,而是指向完全未定义的垃圾内存地址。为应用程序中的每个对象使用单个全局参数指针的更好方法是在相应的main.cpp中声明一次指针(如果你更喜欢那么可能是MainFm.cpp)。然后在Parameters头的底部声明参数指针现在是:

extern Parameters *parameters;

声明指针本身的单行只位于一个cpp文件中,最好是主函数所在的cpp文件。在C ++ Builder中,包含Application-&gt; Initialize(),Application-&gt; CreateForm(...),Application-&gt; Run()调用的cpp是一个很好的候选者。或者,您也可以在任何类方法之前在主应用程序表单cpp文件中声明全局参数指针,并紧跟在项目的头文件包含之后。

以下是两个不同的编码代码示例,以帮助您理解解决范围问题。两个示例都使用最后一行的Parameters头文件的略微修改。请注意,只应选择一个示例供实现使用。同时实现这两种方法应该会导致编译器发出一个令人困惑的错误消息,即声明了两个参数指针(它可能是捕获它的链接器)。

最后一个参数头文件行应该变为:

extern Parameters *parameters; // might want to change this to pgParameters

// 
// pgParameters means global pointer to a Parameters instance
// 

示例1 - Project.cpp声明

// 
// the cpp where Application->Initialize() is called
// Below the C++Builder IDE controlled comment line, immediately below 
// the last USEFORM macro call, have the #include and pointer instance declaration.  
//
#include "Parameters.h"  // the header file where the Parameters class is defined
Parameters *parameters;  // declare the single global pointer for all objects' use 

extern "C" int FormMain()
{
   //
   // the rest of the C++Builder IDE controlled content; leave as is
   //   
}

示例2 - MainForm.cpp声明

// 
// the cpp where the main form constructor body, event handlers, user defined 
// functions, etc. are written.
// Below the C++Builder IDE controlled declaration of the global pointer for 
// the main form, where the default declaration is: 
// 
// TForm1 *Form1;  
//
// code the #include and pointer instance declaration.
//
//------------------------------------------------------------------------
TForm1 *Form1;
#include "Parameters.h"  // the header file where Parameters class is defined
Parameters *parameters;  // declare the single global pointer for all objects' use 

//
// rest of the already existing code...
//

请注意,这两个示例都是故意将参数相关项目分组 引入Parameters头的#include可以与另一个头文件组合在一起     根据需要#include行。这一切都取决于团队编码标准。