我正在使用 QtSDK 4.7.3
我在 (void test()) 中这样做:
mgr = new QNetworkAccessManager();
reply = mgr->get(QNetworkRequest(QUrl("http://developer.qt.nokia.com/fileNotExisting.txt")));
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
SLOT(onError(QNetworkReply::NetworkError)), Qt::ConnectionType::UniqueConnection);
当然,插槽 onError 被称为:
if (networkError == QNetworkReply::NetworkError::ContentNotFoundError)
{
// Messagebox starts an event loop which
// causes this slot to be called again
QMessageBox m;
m.exec();
}
如果我在 onError 插槽中没有消息框/事件循环,则不会发生崩溃并且一切正常。但是当它在那里时,当调用 m.exec() 时会再次调用 onError 插槽。当两个消息框都关闭并且我离开函数 onError 时,应用程序崩溃。发生这种情况时,应用程序会尝试删除/释放内存。错误“访问冲突读取位置”无济于事,并且调用堆栈深入 Qt dll。
我检查了什么:
信号没有连接两次。
尝试在 QApplication 调用它的 exec 函数之前和之后调用 test() 。(不要紧)。
另一个像 HostNotFound 这样的错误不会调用 onError 槽两次。
我所有的代码都在主线程中执行。
尝试断开 onError 插槽,因此它只被调用一次,但它仍然崩溃。
尝试在 onError() 中对请求调用中止。
在 Qt 论坛(帖子)上发布了相同的问题。
谁能帮我弄清楚这里发生了什么?
这是我用于测试的代码:main.cpp
#include "contentnotfound.h"
#include <QtGui/QApplication>
#include <QTimer>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ContentNotFound cnf;
// false: start test after application's event loop have started
if (true) { cnf.test(); }
else { QTimer::singleShot(2000, &cnf, SLOT(test())); }
return a.exec();
}
contentnotfound.h
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QMessageBox>
class ContentNotFound : public QObject
{
Q_OBJECT
public slots:
void test()
{
mgr = new QNetworkAccessManager();
reply = mgr->get(QNetworkRequest(QUrl("http://developer.qt.nokia.com/fileNotExisting.txt")));
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
SLOT(onError(QNetworkReply::NetworkError)), Qt::ConnectionType::UniqueConnection);
}
private slots:
void onError(QNetworkReply::NetworkError networkError)
{
//reply->disconnect(); // Disconnect all signals
if (networkError == QNetworkReply::NetworkError::ContentNotFoundError)
{
// Messagebox starts an event loop which
// causes this slot to be called again
QMessageBox m;
m.exec();
}
}
private:
QNetworkAccessManager* mgr;
QNetworkReply* reply;
};