C++ Qt应用程序在退出时崩溃,操作系统应用;容错堆垫片“;

C++ Qt应用程序在退出时崩溃,操作系统应用;容错堆垫片“;,c++,qt,crash,qml,qtquick2,C++,Qt,Crash,Qml,Qtquick2,我无法隔离导致应用程序在退出时崩溃的原因。更让人困惑的是,它并不总是崩溃,有时崩溃,有时不崩溃,而且似乎是完全任意的 该示例基本上包含一个自定义图像提供程序,该程序将静态GoogleMapsAPI请求加载为PNG图像,以在QML中显示。映像提供程序本身可以工作,我首先怀疑问题可能是在堆栈上实例化网络访问管理器,但事实并非如此,我得到了动态实例化它的相同行为。有趣的是,这次坠机似乎没有什么特别的原因。只是启动和关闭应用程序有时会产生崩溃,而没有任何交互,但在没有任何交互的情况下,它通常不会崩溃。有

我无法隔离导致应用程序在退出时崩溃的原因。更让人困惑的是,它并不总是崩溃,有时崩溃,有时不崩溃,而且似乎是完全任意的

该示例基本上包含一个自定义图像提供程序,该程序将静态GoogleMapsAPI请求加载为PNG图像,以在QML中显示。映像提供程序本身可以工作,我首先怀疑问题可能是在堆栈上实例化网络访问管理器,但事实并非如此,我得到了动态实例化它的相同行为。有趣的是,这次坠机似乎没有什么特别的原因。只是启动和关闭应用程序有时会产生崩溃,而没有任何交互,但在没有任何交互的情况下,它通常不会崩溃。有时,与地图中心和缩放的多次交互不会导致退出时崩溃,但大多数情况下确实如此

另一个疑点是我实例化的事件循环,以便在网络请求完成时“阻止”映像提供程序方法。由于图像提供程序的设计,必须使用请求图像的相同方法返回图像,换句话说,我不能使用“推荐”方法,即仅从一个方法启动请求并通过将其
完成的
信号连接到另一个方法来捕获它。但这似乎也不是问题所在,因为提供商总是设法提供图像,我认为这没有问题。至少不是直接的,但可能是网络接入的一些副作用

顺便说一句,Qt只在首次使用network access manager时发出了一些警告。使用Qt 5.2,我只得到了以下四个:

QSslSocket: cannot resolve TLSv1_1_client_method
QSslSocket: cannot resolve TLSv1_2_client_method
QSslSocket: cannot resolve TLSv1_1_server_method
QSslSocket: cannot resolve TLSv1_2_server_method
QSslSocket: cannot resolve SSL_select_next_proto
。。。在升级到新的5.3.1以希望删除这些警告之后,除了之前的四个警告之外,实际上还出现了两个警告:

QSslSocket: cannot resolve SSL_CTX_set_next_proto_select_cb
QSslSocket: cannot resolve SSL_get0_next_proto_negotiated
也许这些警告与车祸有关

以下是appcrash信息:

  Fault Module Name:    ntdll.dll
  Fault Module Version: 6.1.7601.17725
  Fault Module Timestamp:   4ec49b8f
  Exception Code:   c0000005
  Exception Offset: 000332a0
  OS Version:   6.1.7601.2.1.0.256.1
  Locale ID:    1033
  Additional Information 1: 0a9e
  Additional Information 2: 0a9e372d3b4ad19135b953a78882e789
  Additional Information 3: 0a9e
  Additional Information 4: 0a9e372d3b4ad19135b953a78882e789
平台信息:Windows 7 x64,使用GCC存储32位Qt构建

以下是相关代码:

C++


问题出在图像提供程序类中。我不确定确切的位置,但它在那里,因为没有它,我无法重现崩溃。我之所以能够这样说,是因为在您的情况下,图像提供程序是完全不必要的-QtQuick
image
元素将接受Google API url源并按原样工作。

递归事件循环是一个无休止的麻烦源。使用图像提供程序的设计基本上是不正确的。您需要以其他方式执行。@KubaOber-这就提出了一个问题,如果网络访问管理器本质上是异步的,并且映像提供程序需要以相同的方法请求和返回映像,那么如何使用它实现映像提供程序呢?
QQuickImageProvider
API从根本上被破坏了:(QML引擎在一个单独的线程中运行提供程序有一个难看的解决方法。你真的需要在调试器下运行它,看看它在哪里崩溃。你提供的“appcrash信息”是无用的。
class MapReader : public QQuickImageProvider {
public:
    explicit MapReader() : QQuickImageProvider(QQuickImageProvider::Pixmap, QQmlImageProviderBase::ForceAsynchronousImageLoading) { }

    QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) {
        QNetworkAccessManager m;
        Q_UNUSED(requestedSize)
        Q_UNUSED(size)
        QEventLoop loop;
        QObject::connect(&m, SIGNAL(finished(QNetworkReply*)), &loop, SLOT(quit()));
        QNetworkReply * r = m.get(QNetworkRequest(QUrl(id)));
        loop.exec();

        if (r->error()) {
            qDebug() << "Error: " << r->errorString();
            r->deleteLater();
            return QPixmap();
        }

        QPixmap p;
        p.loadFromData(r->readAll());
        r->deleteLater();
        return p;
    }    
};
Rectangle {
    id: root
    width: 360
    height: 360

    property string url : 'image://map/http://maps.googleapis.com/maps/api/staticmap?center=' + n + ',' + e + '&zoom=' + zoom.value + '&size=' + width  + "x" + height + '&maptype=satellite'
    property real n : 48.858222
    property real e : 2.2945

    Timer {
        id: t
        repeat: false
        interval: 100
        running: false
        onTriggered: {
            placeholder.source = root.url
        }
    }

    function refresh() { if (t.running) t.restart(); else t.start() }

    Image {
        id: placeholder
        anchors.fill: parent
    }

    MouseArea {
        anchors.fill: parent

        onClicked: {
            var xOffset = (mouseX / width - 0.5) * (360 / Math.pow(2, zoom.value))
            var yOffset = (mouseY / height - 0.5) * (360 / Math.pow(2, zoom.value))

            console.log(xOffset + " " + yOffset)

            root.n = root.n - yOffset
            root.e = root.e + xOffset
            root.refresh()
        }
    }

    Slider {
        id: zoom
        value: 17
        maximumValue: 21
        minimumValue: 1
        stepSize: 1
        x: 80
        y: parent.height - 25
        width: parent.width - 90

        onValueChanged: root.refresh()
    }
}