目前,我的转储文件有问题。一般来说,当我的应用程序崩溃时,我使用 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。不幸的是,这个方法没有任何影响。没有转储文件生成。
经过这些尝试后,我尝试在
中使用谷歌breakpadfollowing 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文件,我真的没有办法处理这个问题,有人可以帮助我吗,谢谢!!!!
过去几天,该问题没有进一步的反馈。 @Mike Vine 的回答也肯定解决了这个问题。因此,时间应该很接近。感谢迈克·瓦恩的回答。