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

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&lt;&gt;(); 添加到 ctor 中,请务必更改某些内容。 也许不是,但m_doc 仍然需要指向某些东西才能使用它。 因为在没有首先初始化 m_doc 的情况下使用 m_doc-&gt; 是未定义的行为,实际上任何事情都可能发生,包括在第一轮实际按预期工作的事情,但不是第二轮。 如果您的意思是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&lt;&gt; m_xmlFile; 在标题内,否则谢谢! 是的,我修好了。时间不早了……我要睡觉了>

以上是关于从其他类调用此方法会创建违规读取的主要内容,如果未能解决你的问题,请参考以下文章

从 Swift 中的其他类调用方法

从其他类Objective-C访问方法

Xamarin C# - 从其他类调用异步方法

从Python中其他进程中运行的函数调用类方法

从其他类创建对象

super调用其他类的方法