使用qtcreator进行调试时运行时崩溃

时间:2018-03-15 11:20:23

标签: qt debugging

有一段时间,我无法再调试我的应用程序,每次在调试模式下启动它时都会崩溃。另一方面,只执行它就可以正常运行。

我做了很多不同配置的测试:

  • Windows 7 with mingw32
  • Windows 10 with mingw32
  • Ubuntu with gcc

在Linux上,没问题,一切正常。

在Windows 7或10上,应用程序在打开后立即崩溃,并显示以下消息(两次):

Microsoft Visual C ++运行时库: 此应用程序已请求运行时以不寻常的方式终止它。

输出面板提供以下信息:

Debugging starts
section .gnu_debuglink not found in ...\build-Integration GspvMapviewer-Desktop_Qt_5_9_2_MinGW_32bit-Debug\debug\Integration GspvMapviewer.exe.debug
QML debugging is enabled. Only use this in a safe environment.
QML Debugger: Waiting for connection on port 49727...
Invalid parameter passed to C runtime function.
Invalid parameter passed to C runtime function.
ASSERT: "!m_thread.isRunning()" in file qqmldebugserver.cpp, line 655
Invalid parameter passed to C runtime function.
Invalid parameter passed to C runtime function.
Debugging has finished

编译输出中没有提到问题。

在网上搜索,我无法找到问题的根源。

你知道如何解决这一点吗?

提前谢谢。

EDIT1

的.pro

QT += quick positioning widgets
CONFIG += c++11

DEFINES += QT_DEPRECATED_WARNINGS

SOURCES += \
    main.cpp \
    waypointsfilter.cpp

RESOURCES += gspv.qrc \
    resource.qrc

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

HEADERS += \
    waypointsfilter.h \
    waypointsmodel.h \
    airport.h \
    waypoint.h \
    airportsmodel.h \
    landmark.h \
    runwaymodel.h

OTHER_FILES +=main.qml \
    helper.js \
    images/marker.png \
    images/scale.png \
    images/scale_end.png \
    map/MapComponent.qml \
    map/Marker.qml \
    map/MapSliders.qml \
    menus/MainMenu.qml \
    forms/Message.qml \
    forms/MessageForm.ui.qml

DISTFILES += \
    forms/SplitInterface.qml \
    forms/IME.qml \
    map/SimpleMap.qml \ 
    map/Airport.qml \
    images/BlackWaypoint.bmp \
    map/Runway.qml \
    forms/InitialAirport.qml

的main.cpp

#include "waypointsmodel.h"
#include "waypointsfilter.h"
#include "airportsmodel.h"
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QDebug>
#include <QDateTime>


int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QApplication app(argc, argv);


    WaypointsModel model;
    AirportsModel apModel;

    QVariantMap parameters;
    parameters[QStringLiteral("esri.useragent")] = QStringLiteral("Générateur Simplifié de Plans de Vol");

    model.readFromCSV(QCoreApplication::applicationDirPath() + "/files/Waypoints.txt");
    apModel.readFromTXT(QCoreApplication::applicationDirPath() + "/files/Airports.txt");

    WaypointsFilter proxyModel(&model);


    QQmlApplicationEngine engine;
    engine.addImportPath(QStringLiteral(":/imports"));

    engine.rootContext()->setContextProperty("waypointsFilter", &proxyModel);
    engine.rootContext()->setContextProperty("airportsModel", &apModel);

    engine.load(QUrl(QLatin1String("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    QObject::connect(&engine, SIGNAL(quit()), qApp, SLOT(quit()));

    QObject *item = engine.rootObjects().first();
    Q_ASSERT(item);


// The crash occurs after this line is executed
    QMetaObject::invokeMethod(item, "initializeProviders",
                              Q_ARG(QVariant, QVariant::fromValue(parameters)));


    return app.exec();
}

EDIT2

以下是错误代码的片段:

function getPlugins()
{
    //crash is here !
    var plugin = Qt.createQmlObject ('import QtLocation 5.6; Plugin {}', mainWindow)
    var myArray = new Array()
    for (var i = 0; i<plugin.availableServiceProviders.length; i++) {
        var tempPlugin = Qt.createQmlObject ('import QtLocation 5.6; Plugin {name: "' + plugin.availableServiceProviders[i]+ '"}', mainWindow)

        if (tempPlugin.supportsMapping()
                && !(tempPlugin.name === "itemsoverlay")
                && !(tempPlugin.name === "here")
                && !(tempPlugin.name === "mapbox")
                && !(tempPlugin.name === "mapboxgl"))
            myArray.push(tempPlugin.name)
    }

    myArray.sort()
    return myArray
}

function initializeProviders(pluginParameters)
{

    var parameters = new Array()
    for (var prop in pluginParameters){
        var parameter = Qt.createQmlObject('import QtLocation 5.6; PluginParameter{ name: "'+ prop + '"; value: "' + pluginParameters[prop]+'"}',mainWindow)
        console.log ("plugin name :" + prop + "value : " +pluginParameters[prop] )
        parameters.push(parameter)
    }
    mainWindow.parameters = parameters
    var plugins = getPlugins()
    mainMenu.providerMenu.createMenu(plugins)
    for (var i = 0; i<plugins.length; i++) {
        if (plugins[i] === "esri")
            mainMenu.selectProvider(plugins[i]) //Génère la création de la carte par déclenchement de onSelectProvider
    }
}

我担心的是这个警告:部分未找到.gnu_debuglink

为什么在.exe.debug文件中找不到此部分?

以下是崩溃前的调试状态: Here is the status of debugging just before crash

崩溃后: debug after crash

1 个答案:

答案 0 :(得分:2)

.gnu_debuglink是gdb用于将单独的调试信息与实际二进制文件相关联的机制。它可能与插件加载引起的崩溃有关,或者gdb可能只是通知它与正在加载的其他插件有关。

我怀疑你的问题可能与Qt bug引起的OOM有关,Qt 5.9.5中的fixed。同时,你可以测试是否剥离qtgeoservices_mapboxgld.dll文件可以防止崩溃(在bugreport评论中说过)。

此外,为了使您的代码更健壮,您应该从Qt.createQmlObject中捕获异常,因为如果插件加载失败,则会抛出错误:

try {
    var newObject = Qt.createQmlObject('import QtLocation 5.6; ...);
} catch (error) {
    console.log ("Error loading QML : ")
    for (var i = 0; i < error.qmlErrors.length; i++) {
        console.log("lineNumber: " + error.qmlErrors[i].lineNumber)
        console.log("columnNumber: " + error.qmlErrors[i].columnNumber)
        console.log("fileName: " + error.qmlErrors[i].fileName)
        console.log("message: " + error.qmlErrors[i].message)
    }
}

&#34;传递给C运行时函数的参数无效。&#34;警告消息可能是由Qt在上述错误发生时调用某些C运行时函数引起的。

用于跟踪的通用解决方案&#34;传递给C运行时函数的无效参数。&#34;起源由Dennis Yurichev提供。下面,我为您提供了如何操作的步骤(来自我的环境的路径)。

QML:

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    function initializeProviders(anObject) {
        for (var prop in anObject) {
            console.log("Object item:", prop, "=", anObject[prop])
        }
    }

    Text {
        id: textLabel
        anchors.centerIn: parent
        text: qsTr("text")
    }
}

C ++:

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    QVariantMap parameters;
    parameters[QStringLiteral("esri.useragent")] = QStringLiteral("Générateur Simplifié de Plans de Vol");

    QObject *item = engine.rootObjects().first();
    Q_ASSERT(item);

    QMetaObject::invokeMethod(item, "initializeProviders",
                              Q_ARG(QVariant, QVariant::fromValue(parameters)));

    // Generate error: file open fails
    FILE *pFile = fopen (NULL,"w");
    // fputs with invalid file displays in debug mode "Invalid parameter passed to C runtime function."
    fputs("abc",pFile);
    // fprintf with invalid file crashes the program
    fprintf(pFile, "def\n");

    return app.exec();
}

在命令提示符中:

C:\> SET PATH=%PATH%;C:\Qt\5.9.4\mingw53_32\bin
C:\> cd proj\build-quickTest-Desktop_Qt_5_9_4_MinGW_32bit-Debug\debug
C:\> C:\Qt\Tools\mingw530_32\bin\gdb quickTest.exe
(gdb) break OutputDebugStringA
Function "OutputDebugStringA" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (OutputDebugStringA) pending.
(gdb) r
when it breaks print the backtrace
(gdb) bt
<backtrace...>
(gdb) c
Continuing.
warning: QML debugging is enabled. Only use this in a safe environment.
(gdb) bt
<backtrace...>
(gdb) c
Continuing.
warning: qml: Object item: esri.useragent = Générateur Simplifié de Plans de Vol


Breakpoint 1, 0x74d535fc in OutputDebugStringA ()
   from C:\Windows\syswow64\KernelBase.dll
(gdb) bt
#0  0x74d535fc in OutputDebugStringA ()
   from C:\Windows\syswow64\KernelBase.dll
#1  0x754569c4 in msvcrt!_chkesp () from C:\Windows\syswow64\msvcrt.dll
#2  0x754569d0 in msvcrt!_chkesp () from C:\Windows\syswow64\msvcrt.dll
#3  0x00010001 in ?? ()
#4  0x7543b9b7 in msvcrt!_ftol2_sse_excpt ()
   from C:\Windows\syswow64\msvcrt.dll
#5  0x00000000 in ?? ()
(gdb) c
Continuing.
warning: Invalid parameter passed to C runtime function.

Program received signal SIGSEGV, Segmentation fault.
0x770a2302 in ntdll!RtlEnterCriticalSection ()
   from C:\Windows\SysWOW64\ntdll.dll
(gdb) bt
#0  0x770a2302 in ntdll!RtlEnterCriticalSection ()
   from C:\Windows\SysWOW64\ntdll.dll
#1  0x004080b7 in _lock_file ()
#2  0x00402fe1 in __mingw_vfprintf ()
#3  0x00401656 in fprintf (__stream=0x0,
    __format=0x40b1fa <qMain(int, char**)::{lambda()#3}::operator()() const::qst
ring_literal+154> "def\n")
    at C:/Qt/Tools/mingw530_32/i686-w64-mingw32/include/stdio.h:289
#4  0x00401b2d in qMain (argc=1, argv=argv@entry=0x21319038)
    at ..\quickTest\main.cpp:32
#5  0x00402f05 in WinMain@16 () at qtmain_win.cpp:104
#6  0x0040949d in main ()
(gdb)

我们可以看到用__stream = 0x0调用fprintf会导致段错误。

修改

我使用mapviewer示例进行了一些测试。当我在调试模式下运行它时:

Debugging starts
Invalid parameter passed to C runtime function.
Invalid parameter passed to C runtime function.
terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc
QMutex: destroying locked mutex
Debugging has finished

然后我剥离了qtgeoservices_mapboxgld.dll:

C:\...> SET PATH=C:\Qt\5.9.4\mingw53_32\bin;%PATH%
C:\...> cd C:\Qt\5.9.4\mingw53_32\plugins\geoservices
C:\...> strip qtgeoservices_mapboxgld.dll

在调试模式下剥离运行成功后:

qml: initializeProviders: osm.useragent = QtLocation Mapviewer example
qml: getPlugins: esri
qml: getPlugins: pushing esri
qml: getPlugins: mapbox
qml: getPlugins: pushing mapbox
qml: getPlugins: mapboxgl
qml: getPlugins: pushing mapboxgl
qml: getPlugins: here
qml: getPlugins: pushing here
qml: getPlugins: itemsoverlay
qml: getPlugins: pushing itemsoverlay
qml: getPlugins: osm
qml: getPlugins: pushing osm

这样你至少应该在你的应用程序漏洞中取得进展。

你使用的是哪个Qt和mingw版本?