Я использую Qt 5.11.1 (MSVSC2015 32bit) и QtCreator 4.6.2.
У меня проблемы с анализом XML с помощью QXmlStreamReader. Код написан на основе Пример Qt.
Когда мой код выполняется, он вызывает нарушение доступа в QIODevice.cpp в функции checkWarnMessage.
это образ показывает стек вызовов и точную строку, где произошло нарушение доступа.
Фактический XML более сложен и имеет вложенные элементы. Функции, которые анализируют XML, реализованы так же, как и функция void XbelReader :: readXBEL () из примера Qt (на основе имени элемента для анализа этого элемента вызывается соответствующая функция). Но на этом простом примере мне удалось воспроизвести имеющуюся у меня проблему в реальном решении.
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) можно загрузить из этого ссылка на сайт
РЕДАКТИРОВАТЬ
Я исправил свой пример, как предложил Мантан, и он сработал, как и ожидалось. Я добавил еще одну вещь в 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 допустим в Notepad ++ с плагином XML Tools, а также в xmlvalidation.xml. Когда я выполняю фиксированный пример с новым XML, у меня снова возникает нарушение прав доступа в том же месте, что и на ранее связанном изображении.
Теперь, если я удаляю последний символ «o» из комментария в XML (или любой другой символ из комментария, или, например, «6» из текста элемента 6, или фактически любой символ из XML, сохраняя XML действительным), пример выполнено успешно. И это моя изначальная проблема. У меня есть много комментариев в моем исходном файле XML, в результате чего размер файла превышает 8 КБ. Пока что в качестве обходного пути я удаляю комментарии, чтобы избежать нарушения прав доступа.
Мне не ясно, как длина комментария (или файла) вызывает нарушение прав доступа.
Весь проект можно скачать с этого ссылка на сайт
Проблема в цикле. Обновите это как ниже.
while(xmlReader.readNextStartElement())
{
if(xmlReader.name() == "element1")
ParseElement1(xmlReader);
else if(xmlReader.name() == "element2")
ParseElement2(xmlReader);
else
xmlReader.skipCurrentElement();
}
В вашем коде первый элемент имеет тип ‘element1’, затем сначала он обрабатывается (с первым if
) и они снова дошли до else
где это попытаться пропустить это, которые вызывают проблемы.
Других решений пока нет …