Qt C ++未处理的异常堆栈跟踪 [英] Qt C++ Unhandled exceptions stack trace
问题描述
我正在尝试找出一种方法,以在发生崩溃时获取已部署的c ++应用程序的堆栈跟踪。我尝试了几种方法,并且我认为我的问题与发生异常后的堆栈有关。
I am trying to figure out a way to get the stack trace of a deployed c++ application in the event of a crash. I have tried a couple of approaches and I think my issue is related to the stack after an exception occurs.
我在Qt中创建了一个测试应用程序。这是代码。
I created a test application in Qt. Here is the code.
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中的堆栈跟踪得到以下堆栈。
If I call anotherFunc() and then look at the stack trace in WinDbg I get the following stack.
我认为其中有些
如果我调用badFunc(),这就是我得到的。
If I call badFunc() however this is what I get.
堆栈跟踪从UnhandledExceptionFilter开始。
The stack trace starts at UnhandledExceptionFilter. It seems like the stack is getting messed up by the exception.
在这里,我找到了生成迷你转储的代码。 http://blog.aaronballman.com/2011/05/generating-a -minidump /
Here is where I got the code to generate the mini dumps. http://blog.aaronballman.com/2011/05/generating-a-minidump/
推荐答案
您为 badFunc $ c $发布的堆栈跟踪c>非常好,并且给定您正在使用的实现的预期结果。 MiniDumpWriteDump 使用当前指令指针运行堆栈跟踪,除非您传递SEH异常的 EXCEPTION_POINTERS 通过 MINIDUMP_EXCEPTION_INFORMATION 结构。由于未处理的异常过滤器安装在异常框架的底部,因此从该处调用
MiniDumpWriteDump
会生成您观察到的堆栈跟踪。
The stack trace you posted for badFunc
is perfectly fine, and the expected result, given the implementation you are using. 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 structure. Since the unhandled exception filter is installed at the bottom of the exception frames, calling MiniDumpWriteDump
from there produces the stack trace you observed.
要获得更有用的堆栈跟踪,您需要将 EXCEPTION_POINTERS
传递给 MiniDumpWriteDump
。
To get a more helpful stack trace, you need to pass the EXCEPTION_POINTERS
to MiniDumpWriteDump
.
这只是您正在使用的实现。还有更多内容:
This is just one of many issues with the implementation you are using. There are more:
- 作者似乎很清楚,他们可以通过
nullptr
作为ExceptionParam
参数,然后继续决定始终传递nullptr
。该接口实际上应该提供两个重载:一个带有EXCEPTION_POINTERS
参数,另一个没有。这允许从任何地方调用该功能,但是当从未处理的异常过滤器(后者是迄今为止最常见的用例)中调用时,还可以保留堆栈跟踪。 - 作者引发一个有趣的问题:应用程序中的其他线程应该怎么做? 就目前而言,
MiniDumpWriteDump
已经挂起 all 在进程中进行线程化,然后继续前进。您甚至都别无选择。暂停线程的整个实现(包括排除助手线程的过滤器)是多余的。 - 作者未能解决一个实际问题(香草
MiniDumpWriteDump
以及他们自己的话题暂停执行):线程在任意点被暂停。如果这些线程中的任何一个拥有任何锁(例如全局堆分配互斥锁),那么您将立即死锁。毕竟,MiniDumpWriteDump
还要从进程堆中分配内存。这里的解决方案涉及更多:MiniDumpWriteDump
的调用必须在自己的进程中执行,并且具有适当的IPC。
- The author seems to be well aware, that they can pass
nullptr
for theExceptionParam
parameter, but then moves on to decide to always passnullptr
. The interface should really provide two overloads: One that takes anEXCEPTION_POINTERS
argument, and one without. This allows the functionality to be called from anywhere, but also retains the stack trace, when called from an unhandled exception filter (the latter is by far the most common use case). - The author raises an "interesting question: what should be done with other threads in the application?" As it stands,
MiniDumpWriteDump
already suspends all threads in the process before moving forward. You don't even have a choice there. The entire implementation to suspend threads (including the filter to exclude the helper thread) is superfluous. It needs to go. - The author fails to address a real issue (both of the vanilla
MiniDumpWriteDump
, as well as their own thread suspending implementation): Threads get suspended at arbitrary points. If any of these threads hold any locks (like the global heap allocation mutex), you are in for an instant dead lock. After all,MiniDumpWriteDump
will want to allocate memory from the process heap as well. The solution here is more involved: The call toMiniDumpWriteDump
must be performed in its own process, with appropriate IPC in place.
以上任何一个都是相当重大的错误,需要解决。 已发布,该代码既无用又危险。如果您希望同时实现自己的解决方案,请查看以下资源以获取可靠的信息:
Either of the above is a fairly substantial bug, and needs to be addressed. As published, the code is both useless as well as dangerous. If you feel like implementing your own solution in the meantime, have a look at the following resources for reliable information:
- Effective Minidumps - Part 1
- Effective Minidumps - Part 2
这篇关于Qt C ++未处理的异常堆栈跟踪的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!