草庐IT

c++ - Qt QXmlStreamReader 访问冲突

coder 2024-02-20 原文

我正在使用 Qt 5.11.1(MSVSC2015 32 位)和 QtCreator 4.6.2。 我在使用 QXmlStreamReader 解析 XML 时遇到问题。代码是根据Qt's example编写的. 执行我的代码时,它会在 QIODevice.cpp 的 checkWarnMessage 函数中产生访问冲突。 这image显示调用堆栈和发生访问冲突的确切行。

实际的 XML 更复杂并且具有嵌套元素。解析 XML 的函数的实现方式与 Qt 示例中的 void XbelReader::readXBEL() 函数相同(根据元素名称调用适当的函数来解析该元素)。但是通过这个简单的例子,我成功地重现了我在实际解决方案中遇到的问题。

XML 是:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <element1>1</element1>
    <element2>2</element2>
    <element3>3</element3>
    <element4>4</element4>
    <element5>5</element5>
    <element6>6</element6>
</root>

解析此 XML 的代码是:

#include <string>
#include <stdexcept>
#include <iostream>

#include <QCoreApplication>
#include <QXmlStreamReader>
#include <QFile>
#include <QString>

#define ASSERT_ELEMENT_NAME(NAME) Q_ASSERT(xmlReader.isStartElement() && xmlReader.name() == NAME);

using namespace std;

void OpenFile(const QString& fileName, QXmlStreamReader& xmlReader)
{
    QFile configFile(fileName);
    if (configFile.open(QFile::ReadOnly | QFile::Text) == false)
        throw runtime_error(string("Failed to open file: ") + configFile.errorString().toStdString());

    xmlReader.setDevice(&configFile);
    if (xmlReader.readNextStartElement() == false)
        throw runtime_error("File does not have root element");

    if (xmlReader.name() != "root")
        throw runtime_error("File has invalid root element");
}

void ParseElement1(QXmlStreamReader& xmlReader)
{
    ASSERT_ELEMENT_NAME("element1");

    auto text = xmlReader.readElementText().trimmed();
    auto isOk = false;
    auto value = text.toInt(&isOk);

    if (isOk == false)
        throw runtime_error(string("invalid value: ") + text.toStdString());
    else
        cout << "element1: " << value << endl;
}

void ParseElement2(QXmlStreamReader& xmlReader)
{
    ASSERT_ELEMENT_NAME("element2");

    auto text = xmlReader.readElementText().trimmed();
    auto isOk = false;
    auto value = text.toInt(&isOk);

    if (isOk == false)
        throw runtime_error(string("invalid value: ") + text.toStdString());
    else
        cout << "element2: " << value << endl;
}

int main()
{
    QXmlStreamReader xmlReader;

    OpenFile("config.xml", xmlReader);

    while(xmlReader.readNextStartElement())
    {
        if(xmlReader.name() == "element1")
            ParseElement1(xmlReader);
        if(xmlReader.name() == "element2")
            ParseElement2(xmlReader);
        else
            xmlReader.skipCurrentElement();
    }
}

如果我在主函数中注释两行:

        if(xmlReader.name() == "element2")
            ParseElement2(xmlReader);

不会发生访问冲突。

我真的不知道我做错了什么。还是 QXmlStreamReader 中存在错误?我认为即使我做错了什么,访问冲突也不应该发生在 Qt 的库中。

整个项目(XmlParser.pro、main.cpp 和 config.xml)可以从此link下载

编辑

我已经按照 Manthan 的建议修复了我的示例,并且它按预期工作。我在 XML 中又添加了一件事。我在 element1 之前添加了大型多行注释。注释本身有 8019 个字符,包括空白字符,而整个 XML 文件有 8266 个字符。

XML 现在看起来像

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <!--
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, 
    comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment, comment,
    comment, comment, co
    -->
    <element1>1</element1>
    <element2>2</element2>
    <element3>3</element3>
    <element4>4</element4>
    <element5>5</element5>
    <element6>6</element6>
</root>

我已经使用 XML 工具插件以及 xmlvalidation.xml 检查了 XML 在 Notepad++ 中是否有效。当我使用新的 XML 执行固定示例时,我再次在先前链接的图像上描述的完全相同的位置发生访问冲突。

现在,如果我从 XML 注释中删除最后一个“o”字符(或从注释中删除任何其他字符,或者例如从 element6 的文本中删除“6”,或者实际上从 XML 中删除任何字符,同时保持 XML 有效) ,示例执行成功。这是我原来的问题。我的原始 XML 文件中有很多注释,导致文件大于 8KB。目前,作为解决方法,我删除评论以避免访问冲突。

我不清楚评论(或文件)长度如何导致访问冲突。

整个项目可以从这个link下载

最佳答案

问题出在 while 循环中。更新如下。

while(xmlReader.readNextStartElement())
{
    if(xmlReader.name() == "element1")
        ParseElement1(xmlReader);
    else if(xmlReader.name() == "element2")
        ParseElement2(xmlReader);
    else
        xmlReader.skipCurrentElement();
}

在您的代码中,第一个元素的类型为“element1”,然后首先处理(使用第一个 if),然后再次到达 else 并尝试跳过它,这会导致问题。

关于c++ - Qt QXmlStreamReader 访问冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51978938/

有关c++ - Qt QXmlStreamReader 访问冲突的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  3. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  4. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

  5. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  6. git使用常见问题(提交代码,合并冲突) - 2

    文章目录git常用命令(简介,详细参数往下看)Git提交代码步骤gitpullgitstatusgitaddgitcommitgitpushgit代码冲突合并问题方法一:放弃本地代码方法二:合并代码常用命令以及详细参数gitadd将文件添加到仓库:gitdiff比较文件异同gitlog查看历史记录gitreset代码回滚版本库相关操作远程仓库相关操作分支相关操作创建分支查看分支:gitbranch合并分支:gitmerge删除分支:gitbranch-ddev查看分支合并图:gitlog–graph–pretty=oneline–abbrev-commit撤消某次提交git用户名密码相关配置g

  7. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  8. ruby - 有没有办法从 ruby​​ case 语句中访问表达式? - 2

    我想从then子句中访问c​​ase语句表达式,即food="cheese"casefoodwhen"dip"then"carrotsticks"when"cheese"then"#{expr}crackers"else"mayo"end在这种情况下,expr是食物的当前值(value)。在这种情况下,我知道,我可以简单地访问变量food,但是在某些情况下,该值可能无法再访问(array.shift等)。除了将expr移出到局部变量然后访问它之外,是否有直接访问caseexpr值的方法?罗亚附注我知道这个具体示例很简单,只是一个示例场景。 最佳答案

  9. ruby - 从外部访问类的实例变量 - 2

    我理解(我认为)Ruby中类变量和类的实例变量之间的区别。我想知道如何从该类外部访问该类的实例变量。从内部(即在类方法中而不是实例方法中),它可以直接访问,但是从外部,有没有办法做MyClass.class.[@$#]variablename?我没有任何具体原因要这样做,只是学习Ruby并想知道是否可行。 最佳答案 classMyClass@my_class_instance_var="foo"class上述yield:>>foo我相信Arkku演示了如何从类外部访问类变量(@@),而不是类实例变量(@)。我从这篇文章中提取了上述内

  10. ruby-on-rails - 使用 HTTP.get_response 检索 Facebook 访问 token 时出现 Rails EOF 错误 - 2

    我试图在我的网站上实现使用Facebook登录功能,但在尝试从Facebook取回访问token时遇到障碍。这是我的代码:ifparams[:error_reason]=="user_denied"thenflash[:error]="TologinwithFacebook,youmustclick'Allow'toletthesiteaccessyourinformation"redirect_to:loginelsifparams[:code]thentoken_uri=URI.parse("https://graph.facebook.com/oauth/access_token

随机推荐