Qt C++ 未处理的异常堆栈跟踪
Qt C++ Unhandled exceptions stack trace
我正在尝试找出一种方法来在发生崩溃时获取已部署的 C++ 应用程序的堆栈跟踪。我尝试了几种方法,我认为我的问题与发生异常后的堆栈有关。
我在 Qt 中创建了一个测试应用程序。这是代码。
void miniDumpFunc()
{
MiniDump dump;
dump.Create(L"C:\dmp\dmp.dmp");
}
void anotherFunc()
{
miniDumpFunc();
}
LONG WINAPI OurCrashHandler(EXCEPTION_POINTERS * /*ExceptionInfo*/)
{
miniDumpFunc();
return EXCEPTION_EXECUTE_HANDLER;
}
void badFunc()
{
int *myNull = NULL;
*myNull = 42;
}
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
::SetUnhandledExceptionFilter(OurCrashHandler);
anotherFunc();
return app.exec();
}
如果我调用 anotherFunc() 然后查看 WinDbg 中的堆栈跟踪,我会得到以下堆栈。
我认为这里有一些内联,但看起来是正确的。
如果我调用 badFunc() 但是这就是我得到的结果。
堆栈跟踪从 UnhandledExceptionFilter 开始。堆栈似乎被异常弄乱了。
这是我获得生成小型转储的代码的地方。 http://blog.aaronballman.com/2011/05/generating-a-minidump/
您为 badFunc
发布的堆栈跟踪非常好,并且是预期的结果,考虑到您正在使用的实现。 MiniDumpWriteDump runs a stack trace using the current instruction pointer, unless you are passing the SEH exception's EXCEPTION_POINTERS through the MINIDUMP_EXCEPTION_INFORMATION 结构。由于未处理的异常过滤器安装在异常帧的底部,因此从那里调用 MiniDumpWriteDump
会产生您观察到的堆栈跟踪。
要获得更有用的堆栈跟踪,您需要将 EXCEPTION_POINTERS
传递给 MiniDumpWriteDump
。
这只是 implementation you are using 的众多问题之一。还有:
- 作者似乎很清楚,他们可以为
ExceptionParam
参数传递 nullptr
,但随后又决定 始终 传递nullptr
。该接口实际上应该提供两种重载:一种采用 EXCEPTION_POINTERS
参数,一种不采用。这允许从任何地方调用该功能,但也保留堆栈跟踪,当从未处理的异常过滤器调用时(后者是迄今为止最常见的用例)。
- 作者提出了一个"interesting question: what should be done with other threads in the application?"目前,
MiniDumpWriteDump
已经挂起进程中的所有个线程在前进之前。你甚至没有选择。暂停线程的整个实现(包括排除辅助线程的过滤器)是多余的。它需要去。
- 作者未能解决一个真正的问题(香草
MiniDumpWriteDump
以及他们自己的线程挂起实现):线程在任意点挂起。如果这些线程中的任何一个持有任何锁(比如全局堆分配互斥锁),您就会立即陷入死锁。毕竟,MiniDumpWriteDump
也想从进程堆中分配内存。这里的解决方案涉及更多:对 MiniDumpWriteDump
的调用必须在其自己的进程中执行,并使用适当的 IPC。
以上任何一个都是相当严重的错误,需要解决。由于 published,该代码既无用又危险。如果您想同时实施自己的解决方案,请查看以下资源以获取可靠信息:
我正在尝试找出一种方法来在发生崩溃时获取已部署的 C++ 应用程序的堆栈跟踪。我尝试了几种方法,我认为我的问题与发生异常后的堆栈有关。
我在 Qt 中创建了一个测试应用程序。这是代码。
void miniDumpFunc()
{
MiniDump dump;
dump.Create(L"C:\dmp\dmp.dmp");
}
void anotherFunc()
{
miniDumpFunc();
}
LONG WINAPI OurCrashHandler(EXCEPTION_POINTERS * /*ExceptionInfo*/)
{
miniDumpFunc();
return EXCEPTION_EXECUTE_HANDLER;
}
void badFunc()
{
int *myNull = NULL;
*myNull = 42;
}
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
::SetUnhandledExceptionFilter(OurCrashHandler);
anotherFunc();
return app.exec();
}
如果我调用 anotherFunc() 然后查看 WinDbg 中的堆栈跟踪,我会得到以下堆栈。
我认为这里有一些内联,但看起来是正确的。
如果我调用 badFunc() 但是这就是我得到的结果。
堆栈跟踪从 UnhandledExceptionFilter 开始。堆栈似乎被异常弄乱了。
这是我获得生成小型转储的代码的地方。 http://blog.aaronballman.com/2011/05/generating-a-minidump/
您为 badFunc
发布的堆栈跟踪非常好,并且是预期的结果,考虑到您正在使用的实现。 MiniDumpWriteDump runs a stack trace using the current instruction pointer, unless you are passing the SEH exception's EXCEPTION_POINTERS through the MINIDUMP_EXCEPTION_INFORMATION 结构。由于未处理的异常过滤器安装在异常帧的底部,因此从那里调用 MiniDumpWriteDump
会产生您观察到的堆栈跟踪。
要获得更有用的堆栈跟踪,您需要将 EXCEPTION_POINTERS
传递给 MiniDumpWriteDump
。
这只是 implementation you are using 的众多问题之一。还有:
- 作者似乎很清楚,他们可以为
ExceptionParam
参数传递nullptr
,但随后又决定 始终 传递nullptr
。该接口实际上应该提供两种重载:一种采用EXCEPTION_POINTERS
参数,一种不采用。这允许从任何地方调用该功能,但也保留堆栈跟踪,当从未处理的异常过滤器调用时(后者是迄今为止最常见的用例)。 - 作者提出了一个"interesting question: what should be done with other threads in the application?"目前,
MiniDumpWriteDump
已经挂起进程中的所有个线程在前进之前。你甚至没有选择。暂停线程的整个实现(包括排除辅助线程的过滤器)是多余的。它需要去。 - 作者未能解决一个真正的问题(香草
MiniDumpWriteDump
以及他们自己的线程挂起实现):线程在任意点挂起。如果这些线程中的任何一个持有任何锁(比如全局堆分配互斥锁),您就会立即陷入死锁。毕竟,MiniDumpWriteDump
也想从进程堆中分配内存。这里的解决方案涉及更多:对MiniDumpWriteDump
的调用必须在其自己的进程中执行,并使用适当的 IPC。
以上任何一个都是相当严重的错误,需要解决。由于 published,该代码既无用又危险。如果您想同时实施自己的解决方案,请查看以下资源以获取可靠信息: