我正在尝试创建一个配置类,它使用rapidxml从xml读取数据。
因此,我有一个私有的xml_document
,我在构造函数中解析:
class Config
{
public:
Config();
~Config();
/*returns the first found node*/
xml_node<>* findNode(const char* name);
/*get an configuration value. It's always a char*/
char* getConfigValue(const char* name);
private:
rapidxml::xml_document<>* m_doc;
};
//cpp
Config::Config()
{
m_doc = new xml_document<>();
rapidxml::file<> xmlFile("config.xml");
m_doc->parse<0>(xmlFile.data());
//LOG(getConfigValue("width")); // here it works
}
xml_node<>* Config::findNode(const char* name)
{
return m_doc->first_node()->first_node(name);
}
char* Config::getConfigValue(const char* name){
return m_doc->first_node()->first_node(name)->value();
}
在wWinMain
内部,我创建了一个配置对象并尝试调用方法。
Config* config = new Config();
LOG(config->findNode("width")->value()); // this does create violation reading
但是,如果我将相同的行放入Config类的构造函数中,它可以正常工作。这里出了什么问题?
答案 0 :(得分:2)
我不熟悉快速xml,但谷歌快速搜索告诉我:
http://rapidxml.sourceforge.net/manual.html
RapidXml是一种原位解析器,它可以实现非常高的性能 解析速度。原位意味着解析器不会复制 字符串。相反,它将指针放在DOM中的源文本中 层次结构。
3.1源文本的生命周期
原位解析要求源文本至少有效 文档对象。如果源文本被销毁,则名称和值为 DOM树中的节点也将被销毁。另外, 空白处理,字符实体翻译和 字符串的零终止需要修改源文本 解析期间(但请参见非破坏性模式)。这使得文本 一旦RapidXml解析它就无法进行进一步处理。
所以我从中得到的是你不能只拥有 rapidxml :: file&lt;&gt; xmlFile(&#34; config.xml&#34;); 是一个堆栈变量,因为xml_document-&gt; parse()将创建一个直接指向xmlFile内存的树。所以xmlFile必须在内存中至少与xml_document一样长,否则你将拥有无效数据。这意味着xmlFile需要是Config类的成员。另外,我没有看到你初始化m_doc,你刚刚省略了一些代码吗?否则它应该早点抱怨而且永远不会工作。此外,您应该始终检查以确保返回指针的函数在访问之前不返回null,以避免读取违规。
所以你真正想要的是这样的:
class Config
{
public:
Config();
~Config();
/*returns the first found node*/
xml_node<>* findNode(const char* name);
/*get an configuration value. It's always a char*/
char* getConfigValue(const char* name);
private:
rapidxml::file<> m_xmlFile;
rapidxml::xml_document<> m_doc;
};
//cpp
Config::Config()
: m_xmlFile("config.xml")
{
m_doc.parse<0>(m_xmlFile.data());
}
xml_node<>* Config::findNode(const char* name)
{
if (m_doc.first_node())
{
return m_doc.first_node()->first_node(name);
}
return 0;
}
char* Config::getConfigValue(const char* name)
{
if (m_doc.first_node())
{
xml_node<>* node = m_doc.first_node()->first_node(name);
if (node)
{
return node->value();
}
}
return 0;
}