读取访问冲突第二次创建 QDomElement
Read access violation creating a QDomElement the second time
我写了一个class来处理一个XML文件。 class 在构建时加载文件并在销毁时保存它。当 class 处于活动状态时,我有几个 getter 和 setter 函数来更改值。其中之一是记录一些文件重命名的功能。在每次调用时,它都会为 elem_renames.
创建一个新的子元素
void DataElementHandle::renamed(QString new_name, QString old_name)
{
QDomElement elem_ren = xml_doc.createElement("renamed");
QDomAttr att = xml_doc.createAttribute("time");
att.setValue(QDateTime::currentDateTime().toString(Qt::ISODate));
elem_ren.setAttributeNode(att);
QDomText t = xml_doc.createTextNode(old_name + " -> " + new_name);
elem_ren.appendChild(t);
elem_renames.appendChild(elem_ren);
}
问题: 现在,我创建 DataElementHandle class 并为文件的每次更改调用重命名函数。但是我每次调用该函数时,我的程序都会崩溃并显示以下错误消息:
Exception thrown: read access violation.
The error is thrown in the first line of the function.
我不明白为什么会这样。我想我不能覆盖 QDomElement,因为在第一次调用时创建的元素仍然有一个 link。但是怎么办?它应该在函数结束时消失。
我将 Qt 5.8 与 Visual Studio 2015 和 Visual Leak Detector 一起使用。
头文件:
// Version
const quint32 version = 1;
// Doc file path
QString file_path;
bool load_file_ok;
// Doc
QDomDocument xml_doc;
QDomElement root;
// First root elements
QDomElement elem_renames;
如果 XML 文件不存在,将像这样创建一个新模板,并将保存到析构函数中的文件中。
xml_doc = QDomDocument("data_xml");
root = xml_doc.createElement("root");
root.setAttribute("version", QString::number(version));
xml_doc.appendChild(root);
elem_renames= xml_doc.createElement("renames");
root.appendChild(elem_renames);
编辑 1: 我已经建立了一个测试项目,它运行良好。我必须更详细地调查问题。
已解决!
我真蠢。我有这样的设置。我在 for 循环中声明并初始化了指向 XML class 的指针。因为我在下面的 if 语句中删除了旧的并创建了一个新的 class,所以我第一次在 if 语句中初始化了指针,然后在第二次将其删除。
#include <QCoreApplication>
#include <QDomDocument>
#include <QFile>
#include <QDateTime>
#include <QString>
#include <QDebug>
class TestDomClass
{
public:
TestDomClass(QString file_path) :
path(file_path)
{
xml_doc = QDomDocument("data_xml");
root = xml_doc.createElement("root");
root.setAttribute("version", QString::number(version));
xml_doc.appendChild(root);
elem_renames= xml_doc.createElement("renames");
root.appendChild(elem_renames);
}
~TestDomClass()
{
QFile file(path);
if(!file.open(QIODevice::WriteOnly | QIODevice::Text))
{
// TODO
qDebug() << "Failed to open file for writing!";
}
else
{
QTextStream stream(&file);
stream << xml_doc.toString();
}
if(file.isOpen())
{
file.close();
}
}
void renamed(QString new_name, QString old_name)
{
QDomElement elem_ren = xml_doc.createElement("renamed");
QDomAttr att = xml_doc.createAttribute("time");
att.setValue(QDateTime::currentDateTime().toString(Qt::ISODate));
elem_ren.setAttributeNode(att);
QDomText t = xml_doc.createTextNode(old_name + " -> " + new_name);
elem_ren.appendChild(t);
elem_renames.appendChild(elem_ren);
}
private:
QString path;
// Version
const quint32 version = 1;
// Doc
QDomDocument xml_doc;
QDomElement root;
// First root elements
QDomElement elem_renames;
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
TestDomClass *t = Q_NULLPTR; // <-- This line was in the for loop
for(int a = 0; a < 10; ++a)
{
delete t;
t = new TestDomClass("test_" + QString::number(a) + ".xml");
for(int i = 0; i < 10; ++i)
{
qDebug() << "Round: " << i;
t->renamed(QString::number(10*a + i), QString::number(10*a + 10-i));
}
}
delete t;
return a.exec();
}
我写了一个class来处理一个XML文件。 class 在构建时加载文件并在销毁时保存它。当 class 处于活动状态时,我有几个 getter 和 setter 函数来更改值。其中之一是记录一些文件重命名的功能。在每次调用时,它都会为 elem_renames.
创建一个新的子元素void DataElementHandle::renamed(QString new_name, QString old_name)
{
QDomElement elem_ren = xml_doc.createElement("renamed");
QDomAttr att = xml_doc.createAttribute("time");
att.setValue(QDateTime::currentDateTime().toString(Qt::ISODate));
elem_ren.setAttributeNode(att);
QDomText t = xml_doc.createTextNode(old_name + " -> " + new_name);
elem_ren.appendChild(t);
elem_renames.appendChild(elem_ren);
}
问题: 现在,我创建 DataElementHandle class 并为文件的每次更改调用重命名函数。但是我每次调用该函数时,我的程序都会崩溃并显示以下错误消息:
Exception thrown: read access violation. The error is thrown in the first line of the function.
我不明白为什么会这样。我想我不能覆盖 QDomElement,因为在第一次调用时创建的元素仍然有一个 link。但是怎么办?它应该在函数结束时消失。
我将 Qt 5.8 与 Visual Studio 2015 和 Visual Leak Detector 一起使用。
头文件:
// Version
const quint32 version = 1;
// Doc file path
QString file_path;
bool load_file_ok;
// Doc
QDomDocument xml_doc;
QDomElement root;
// First root elements
QDomElement elem_renames;
如果 XML 文件不存在,将像这样创建一个新模板,并将保存到析构函数中的文件中。
xml_doc = QDomDocument("data_xml");
root = xml_doc.createElement("root");
root.setAttribute("version", QString::number(version));
xml_doc.appendChild(root);
elem_renames= xml_doc.createElement("renames");
root.appendChild(elem_renames);
编辑 1: 我已经建立了一个测试项目,它运行良好。我必须更详细地调查问题。
已解决! 我真蠢。我有这样的设置。我在 for 循环中声明并初始化了指向 XML class 的指针。因为我在下面的 if 语句中删除了旧的并创建了一个新的 class,所以我第一次在 if 语句中初始化了指针,然后在第二次将其删除。
#include <QCoreApplication>
#include <QDomDocument>
#include <QFile>
#include <QDateTime>
#include <QString>
#include <QDebug>
class TestDomClass
{
public:
TestDomClass(QString file_path) :
path(file_path)
{
xml_doc = QDomDocument("data_xml");
root = xml_doc.createElement("root");
root.setAttribute("version", QString::number(version));
xml_doc.appendChild(root);
elem_renames= xml_doc.createElement("renames");
root.appendChild(elem_renames);
}
~TestDomClass()
{
QFile file(path);
if(!file.open(QIODevice::WriteOnly | QIODevice::Text))
{
// TODO
qDebug() << "Failed to open file for writing!";
}
else
{
QTextStream stream(&file);
stream << xml_doc.toString();
}
if(file.isOpen())
{
file.close();
}
}
void renamed(QString new_name, QString old_name)
{
QDomElement elem_ren = xml_doc.createElement("renamed");
QDomAttr att = xml_doc.createAttribute("time");
att.setValue(QDateTime::currentDateTime().toString(Qt::ISODate));
elem_ren.setAttributeNode(att);
QDomText t = xml_doc.createTextNode(old_name + " -> " + new_name);
elem_ren.appendChild(t);
elem_renames.appendChild(elem_ren);
}
private:
QString path;
// Version
const quint32 version = 1;
// Doc
QDomDocument xml_doc;
QDomElement root;
// First root elements
QDomElement elem_renames;
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
TestDomClass *t = Q_NULLPTR; // <-- This line was in the for loop
for(int a = 0; a < 10; ++a)
{
delete t;
t = new TestDomClass("test_" + QString::number(a) + ".xml");
for(int i = 0; i < 10; ++i)
{
qDebug() << "Round: " << i;
t->renamed(QString::number(10*a + i), QString::number(10*a + 10-i));
}
}
delete t;
return a.exec();
}