从其他类调用此方法会创建违规读取

时间:2014-04-17 06:55:34

标签: c++ class methods access-violation rapidxml

我正在尝试创建一个配置类,它使用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类的构造函数中,它可以正常工作。这里出了什么问题?

1 个答案:

答案 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;
}