另一个线程中的堆异常无法生成转储文件C++

问题描述 投票:0回答:1

目前,我的转储文件有问题。一般来说,当我的应用程序崩溃时,我使用 win32 api MiniDumpWriteDump 生成转储文件。在大多数情况下,它非常有用。但是,我发现当另一个线程发生Heap Exception时,无法生成转储文件。迷你版在以下部分重现: 主程序 //main.cpp文件

LONG WINAPI createMinidump(_EXCEPTION_POINTERS *apExceptionInfo)
{
    HMODULE mhLib = ::LoadLibraryA("dbghelp.dll");
    MINIDUMPWRITEDUMP pDump = (MINIDUMPWRITEDUMP)::GetProcAddress(mhLib, "MiniDumpWriteDump");

    HANDLE  hFile = ::CreateFileA("core.dmp", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,
        FILE_ATTRIBUTE_NORMAL, NULL);

    _MINIDUMP_EXCEPTION_INFORMATION ExInfo;
    ExInfo.ThreadId = ::GetCurrentThreadId();
    ExInfo.ExceptionPointers = apExceptionInfo;
    ExInfo.ClientPointers = FALSE;

    pDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpWithFullMemory , &ExInfo, NULL, NULL);
    ::CloseHandle(hFile);
    
    return EXCEPTION_CONTINUE_SEARCH;
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    SetUnhandledExceptionFilter(ExceptionHandler);
    
    MainWindow w;
    w.show();

    return a.exec();
}

主窗口.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QLoggingCategory>
#include "testth.h"
#include <QThread>

Q_DECLARE_LOGGING_CATEGORY(MainWindowModule)

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
private:
signals:
    void testsignal();

private slots:

    void on_pushButton_clicked(bool checked);

private:
    Ui::MainWindow *ui;

    TestTh* m_t{Q_NULLPTR};
    QObject* m_To{Q_NULLPTR};

    QThread m_TestTH{};
};
#endif // MAINWINDOW_H

//主窗口.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <qnetworkconfigmanager.h>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <qevent.h>
#include <QFile>
#include <QFileInfo>

Q_LOGGING_CATEGORY(MainWindowModule,"Main.Window.Module",QtMsgType::QtWarningMsg)

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow),m_t{new TestTh()}
{
    ui->setupUi(this);

    this->m_t->moveToThread(&m_TestTH);

    this->m_TestTH.start();

    connect(this,&MainWindow::testsignal,this->m_t,&TestTh::testSlot);
}

MainWindow::~MainWindow()
{
    this->m_TestTH.quit();

    this->m_TestTH.wait();

    delete ui;
}

void MainWindow::on_pushButton_clicked(bool checked)
{
//    this->m_To->thread();

    emit this->testsignal();
}

测试.cpp

#ifndef TESTTH_H
#define TESTTH_H

#include <QObject>
#include <QThread>

class TestTh : public QObject
{
    Q_OBJECT
public:
    TestTh();
    virtual ~TestTh()=default;
public slots:
    void testSlot();
private:

    QObject* m_A{};
    QObject* m_B{};

};

#endif // TESTTH_H

测试.cpp

#include "testth.h"
#include <QDebug>

TestTh::TestTh()
{

}

void TestTh::testSlot()
{
    auto d=new int[1000];
    delete []d;
    delete []d;
    qDebug()<<"test slot func";
}

在上面的代码中,当我按下按钮时应用程序将崩溃。因为,我双重删除了成员 testSlot 中的数组。但是,没有生成任何转储文件。经过一番探索,我被告知 api MiniDumpWriteDump 应该在目标进程中调用。因此,我对我的项目进行了一些修改,如以下部分所示:

#include "mainwindow.h"

//#include <Windows.h>
#include <QApplication>
#include <QFile>
#include <QDeadlineTimer>
#include <QDebug>
#include <QSaveFile>
#include <QStringBuilder>
#include <QTextStream>
#include <mutex>
#include <QDateTime>

#include <QFileInfo>
//#include <minidumpapiset.h>
#include <io.h>
#include <QScopedPointer>
#include <QProcess>

auto WINAPI ExceptionHandler(LPEXCEPTION_POINTERS pException)->long
{
    QScopedPointer<QProcess> anotherExe{new QProcess()};
    anotherExe->setWorkingDirectory(qApp->applicationDirPath());
    anotherExe->setProgram(qApp->applicationDirPath() % QStringLiteral("/CrashDumpGuardor.exe"));

    auto pidPro=QString::number(GetCurrentProcessId());

    auto threadId=GetCurrentThreadId();

    char exceptionContent[32768];

    sprintf_s(exceptionContent,sizeof(exceptionContent)/sizeof (exceptionContent[0]),"%p",pException);

    anotherExe->setArguments(QStringList{pidPro,QString::number(threadId),QString::fromLatin1(exceptionContent),qApp->applicationDirPath()});
    anotherExe->start();
    anotherExe->waitForFinished();

    return TRUE;
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    SetUnhandledExceptionFilter(ExceptionHandler);
    
    MainWindow w;
    w.show();

    return a.exec();
}

有关更多详细信息,我将 minidumpwritedump 移动到另一个名为 CrashDumpGuardor 的项目,该项目生成一个名为 CrashDumpGuardor.exe 的 exe,该 exe 放置在我的崩溃应用程序目录中。我将创建子进程使用一些参数调用 CrashDumpGuardor.exe。不幸的是,这个方法没有任何影响。没有转储文件生成。

经过这些尝试后,我尝试在

中使用谷歌breakpad
following section:
#include <QFileInfo>
#include <io.h>
#include <QScopedPointer>
#include <QProcess>
#include "breakpad/client/windows/handler/exception_handler.h"
using namespace google_breakpad;

static bool callback(const wchar_t *dump_path, const wchar_t *id,
    void *, EXCEPTION_POINTERS *,
    MDRawAssertionInfo *,
    bool succeeded) {
    if (succeeded)
        qWarning("Dump file created in %s, dump guid is %ws\n", dump_path, id);
    else
        qWarning("Dump failed\n");
    return succeeded;
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    ExceptionHandler eh(qApp->applicationDirPath().toStdWString().c_str(), NULL, callback, NULL,
                        ExceptionHandler::HANDLER_ALL);


    MainWindow w;
    w.show();

    return a.exec();
}

但是也没有生成dump文件,我真的没有办法处理这个问题,有人可以帮助我吗,谢谢!!!!

c++ windows qt exception dump
1个回答
0
投票

过去几天,该问题没有进一步的反馈。 @Mike Vine 的回答也肯定解决了这个问题。因此,时间应该很接近。感谢迈克·瓦恩的回答。

© www.soinside.com 2019 - 2024. All rights reserved.