我正在试图找到一种方法来在发生崩溃时获取已部署的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中的堆栈跟踪,我会得到以下堆栈。
我认为这里有一些内容,但它看起来是正确的。
堆栈跟踪从UnhandledExceptionFilter开始。似乎堆栈被异常搞砸了。
这是我获取生成小型转储的代码的地方。 http://blog.aaronballman.com/2011/05/generating-a-minidump/
答案 0 :(得分:4)
根据您使用的实现,您为badFunc
发布的堆栈跟踪完全正常,并且是预期的结果。 MiniDumpWriteDump使用当前指令指针运行堆栈跟踪,除非您通过EXCEPTION_POINTERS结构传递SEH异常MINIDUMP_EXCEPTION_INFORMATION。由于未处理的异常过滤器安装在异常帧的底部,因此从那里调用MiniDumpWriteDump
会产生您观察到的堆栈跟踪。
要获得更有用的堆栈跟踪,您需要将EXCEPTION_POINTERS
传递给MiniDumpWriteDump
。
这只是implementation you are using的许多问题之一。还有更多:
nullptr
获取ExceptionParam
参数,但接着决定始终传递nullptr
。接口应该真正提供两个重载:一个接受EXCEPTION_POINTERS
参数,一个不接受。这允许从任何地方调用功能,但是当从未处理的异常过滤器调用时也保留堆栈跟踪(后者是迄今为止最常见的用例)。MiniDumpWriteDump
已经暂停所有线程在前进的过程中。你甚至没有选择。挂起线程的整个实现(包括用于排除辅助线程的过滤器)是多余的。它需要去。MiniDumpWriteDump
以及他们自己的线程暂停实现):线程在任意点被挂起。如果这些线程中的任何一个持有任何锁(例如全局堆分配互斥锁),那么您将立即执行死锁。毕竟,MiniDumpWriteDump
也希望从进程堆中分配内存。这里的解决方案更为复杂:对MiniDumpWriteDump
的调用必须在自己的流程中执行,并配备适当的IPC。上述任何一个都是一个相当大的错误,需要解决。作为published,代码既无用也有危险。如果您想在此期间实施自己的解决方案,请查看以下资源以获取可靠信息: