从其他类调用此方法会创建违规读取
Posted
技术标签:
【中文标题】从其他类调用此方法会创建违规读取【英文标题】:Calling this method from other class creates violation reading 【发布时间】:2014-04-17 06:55:33 【问题描述】:我正在尝试创建一个配置类,它使用 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 类的构造函数中,则它可以正常工作。这里出了什么问题?
【问题讨论】:
您似乎没有在任何地方初始化m_doc
。
如果将 m_doc = new xml_document<>();
添加到 ctor 中,请务必更改某些内容。
也许不是,但m_doc
仍然需要指向某些东西才能使用它。
因为在没有首先初始化 m_doc
的情况下使用 m_doc->
是未定义的行为,实际上任何事情都可能发生,包括在第一轮实际按预期工作的事情,但不是第二轮。
如果您的意思是LOG()
行仍然给出错误,您可能需要考虑发布mcve。
【参考方案1】:
我对快速 xml 不熟悉,但快速 google 搜索告诉我:
http://rapidxml.sourceforge.net/manual.html
RapidXml 是一个原位解析器,它可以实现非常高的 解析速度。原位意味着解析器不会复制 字符串。相反,它在 DOM 中放置指向源文本的指针 层次结构。
3.1 源文本的生命周期
原位解析要求源文本的寿命至少与 文档对象。如果源文本被破坏,名称和值 DOM 树中的节点也会被销毁。此外, 空白处理、字符实体翻译和 字符串的零终止要求修改源文本 在解析期间(但请参阅非破坏性模式)。这使得文本 一旦被 RapidXml 解析,就无法进一步处理。
所以我从中得到的是,你不能只是让 rapidxml::file xmlFile("config.xml"); 作为 xml_document->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;
【讨论】:
有一个小错字。应该是rapidxml::file<> m_xmlFile;
在标题内,否则谢谢!
是的,我修好了。时间不早了……我要睡觉了>
以上是关于从其他类调用此方法会创建违规读取的主要内容,如果未能解决你的问题,请参考以下文章