chi*_*uba 6 c++ qt access-violation qnetworkaccessmanager
我有一个很大的问题,我实际上认为我已经解决了它。我有一个使用 QNetworkAccessManager 的应用程序。这个QNAM位于一个类中。当我在此 QNAM 上执行请求时,所有请求都在一个包装器中完成,该包装器保存回复并对其执行重试逻辑
例如,如果我在构造函数中有一个 putBlob(继承自 baseRequest),我会传递对 QNAM 的引用。我在其上执行请求并保存指向回复的指针。然后回复将是包装器子项,因此 QNAM 不再拥有它的所有权。包装器是保存 QNAM 的原始类的子类。
类有一个 QNAM,以及子级“putBlobRequest”,其子级有“QNetworkReply*”
现在的问题是,当用户想要取消时,应该删除主对象及其中的所有内容。包装器还应该中止其 QNetworkReply 并断开连接(以便它不会调用 finish())
我的 baseRequest 析构函数(它保存 QNetworkReply 并且是它的父级)看起来像这样:
if(_reply) {
if(_reply->isRunning()) {
_reply->disconnect(SIGNAL(finished()));
_reply->disconnect(SIGNAL(uploadProgress(qint64, qint64)));
_reply->abort();
}
}
Run Code Online (Sandbox Code Playgroud)
当包装器在保存它的类中被杀死时,删除就完成了。(对吗?)
这有时有效,但有时我会遇到巨大的访问冲突,并且所有内容都会因以下调用堆栈而崩溃:
QtCored4.dll!QObject::disconnect(const QObject * sender, const char * signal, const QObject * receiver, const char * method) Line 2891 + 0x8 bytes C++
QtNetworkd4.dll!QNetworkReplyImpl::abort() Line 874 + 0x18 bytes C++
FrameworkAzure.dll!BaseRequest::~BaseRequest() Line 129 + 0xa bytes C++
FrameworkAzure.dll!PutBlobRequest::~PutBlobRequest() Line 24 + 0x5e bytes C++
FrameworkAzure.dll!PutBlobRequest::`scalar deleting destructor'() + 0xb bytes C++
FrameworkAzure.dll!AzureBlobStorageProvider::~AzureBlobStorageProvider() Line 41 + 0xa8 bytes C++
Run Code Online (Sandbox Code Playgroud)
因此,首先调用 abort() ,它调用以下内容:
if (d->outgoingData)
disconnect(d->outgoingData, 0, this, 0); <--- we go in here
Run Code Online (Sandbox Code Playgroud)
这将我带到 QOBject.cpp 中的第 2891 行:
const QMetaObject *smeta = sender->metaObject();
Run Code Online (Sandbox Code Playgroud)
它因错误而崩溃:
CloudSync.exe 中 0x66c2c490 (QtCored4.dll) 处出现未处理的异常:0xC0000005:读取位置 0xdddddddd 时出现访问冲突。
地址“0xdddddddd”是“发送者”。
为什么发送者对象不可读?我究竟做错了什么?请帮忙!
编辑:
还尝试过:
if(_reply) {
if(_reply->isRunning()) {
disconnect(_reply, SIGNAL(finished()), this, SLOT(handleFinishedRequest()));
_reply->abort();
}
}
Run Code Online (Sandbox Code Playgroud)
我还断开了派生的 putBlob 中的 uploadProgress。也尝试过没有断开连接,但遇到了“发件人”被侵犯的相同问题
就我而言,我有一个replyFinished 函数,如下所示:
void MyClass::replyFinished(QNetworkReply *reply)
{
...
delete reply;
}
Run Code Online (Sandbox Code Playgroud)
在我的程序中,这个函数是通过 QNetworkAccessManager 连接的,因此即使我调用了disconnect(reply, ...),回复也不会与它断开连接。命令中止将触发此函数(replyFinished)并删除回复,我再删除一次(通过reply->deleteLater())并导致崩溃。
解决办法:添加一个属性来回复并检查它们。
disconnect(reply, nullptr, this, nullptr);
reply->setProperty("deleting", 1);
reply->abort();
...
void MyClass::replyFinished(QNetworkReply *reply)
{
if (reply->property("deleting").isValid())
return;
...
delete reply;
}
Run Code Online (Sandbox Code Playgroud)