我有一个很大的问题,我认为我解决了它。我有一个使用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();
}
}
当包装器在包含它的类中被终止时,删除就完成了。(对吗?)
这有时会起作用,但有时我会遇到严重的访问冲突,所有内容都会因以下callstack而崩溃:
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++
首先调用abort()调用以下内容:
if (d->outgoingData)
disconnect(d->outgoingData, 0, this, 0); <--- we go in here
这将我带到QOBject.cpp中的第2891行:
const QMetaObject *smeta = sender->metaObject();
它与错误崩溃:
CloudSync.exe中0x66c2c490(QtCored4.dll)的未处理异常:0xC0000005:访问冲突读取位置0xdddddddd。
地址“0xdddddddd”是“发件人”。
为什么发件人对象不可读?我究竟做错了什么?请帮忙!
编辑:
也尝试过:
if(_reply) {
if(_reply->isRunning()) {
disconnect(_reply, SIGNAL(finished()), this, SLOT(handleFinishedRequest()));
_reply->abort();
}
}
我还断开了在dervied putBlob中的uploadProgress。也尝试没有断开,但有相同的问题,“发件人”被违反
答案 0 :(得分:0)
对于我来说,我具有的replyFinished功能如下:
void MyClass::replyFinished(QNetworkReply *reply)
{
...
delete reply;
}
在我的程序中,此函数通过QNetworkAccessManager连接,因此即使我调用了断开连接(reply,...),回复也不会断开。命令 abort 将触发此功能(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;
}