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

C++ STL map exception. (root of nonmutable tree)

本文关键字:不可变 映射 异常 C++STL      更新时间:2023-10-16

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

_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;

更新版本1我对stacktrace的最后一个函数是getProperty。这是getProperty:的代码

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

此代码在主表单中运行良好,但在任何其他表单/中调用异常

如果你有一点时间,我可以在电子邮件上提供一个小程序来说明这个问题。

在parameters类头文件中声明全局使用的参数指针似乎导致了范围问题。这样想吧,每次使用#include引入包含最后一行的头文件时,都会声明并创建另一个指针实例。每次都会在parameters头文件的底部声明参数的指针实例。但是,参数.h在中被引入的次数很多

#include "Parameters.h" 

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

extern Parameters *parameters;

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

以下是两个不同的代码片段示例,有助于理解解决作用域问题。这两个示例都在最后一行对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可以与其他头文件分组#根据需要包括线条。这完全取决于团队编码标准。