我正在使用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插槽中没有messagebox/eventloop,则没有崩溃,并且一切正常。但是当它存在时,则在调用m.exec()时会再次调用onError插槽。
当两个消息框都关闭并且我离开函数onError时,应用程序崩溃。
发生这种情况时,应用程序将尝试删除/释放内存。错误“访问冲突读取位置”无济于事,并且调用堆栈深入Qt dll。

我检查了什么:
信号未连接两次。
尝试在QApplication调用exec函数之前和之后调用test()。 (没关系)。
另一个类似HostNotFound的错误将不会两次调用onError插槽。
我所有的代码都在主线程中执行。
尝试断开onError插槽,因此仅被调用一次,但仍然崩溃。
尝试在onError()中的请求上调用中止。
在Qt论坛(post)上发布了相同的问题。

有人可以帮我弄清楚这里发生了什么吗?

这是我用于测试的代码:
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;

};

最佳答案

Qt https://bugreports.qt.io/browse/QTBUG-16333

用排队的人修改连接可以解决此问题:

contentnotfound.h:

#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QMessageBox>

class ContentNotFound : public QObject
{
Q_OBJECT

public slots:
void test()
{
    qRegisterMetaType<QNetworkReply::NetworkError>("QNetworkReply::NetworkError");
    mgr = new QNetworkAccessManager(this);
    reply = mgr->get(QNetworkRequest(QUrl("http://developer.qt.nokia.com/fileNotExisting.txt")));

    connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
        SLOT(onError(QNetworkReply::NetworkError)), Qt::QueuedConnection);
}

private slots:
void onError(QNetworkReply::NetworkError networkError)
{
    //reply->disconnect(); // Disconnect all signals

    if (networkError == QNetworkReply::ContentNotFoundError)
    {
        // Messagebox starts an event loop which
        // causes this slot to be called again
        QMessageBox m;
        m.exec();
    }
}

private:
QNetworkAccessManager* mgr;
QNetworkReply* reply;

};

关于c++ - 当在错误插槽中启动事件循环时,发生ContentNotFoundError时,QNetworkReply发出两次错误信号,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7650978/

10-11 22:54