简体   繁体   English

Qt C ++未处理的异常堆栈跟踪

[英]Qt C++ Unhandled exceptions stack trace

I am trying to figure out a way to get the stack trace of a deployed c++ application in the event of a crash. 我试图找到一种方法来获取崩溃时部署的c ++应用程序的堆栈跟踪。 I have tried a couple of approaches and I think my issue is related to the stack after an exception occurs. 我尝试了几种方法,我认为我的问题与异常发生后的堆栈有关。

I created a test application in Qt. 我在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();
}

If I call anotherFunc() and then look at the stack trace in WinDbg I get the following stack. 如果我调用anotherFunc()然后查看WinDbg中的堆栈跟踪,我得到以下堆栈。

I think there is some in-lining going on here, but it looks about right. 我认为这里有一些内在的东西,但它看起来是正确的。

If I call badFunc() however this is what I get. 如果我调用badFunc()然而这就是我得到的。

The stack trace starts at UnhandledExceptionFilter. 堆栈跟踪从UnhandledExceptionFilter开始。 It seems like the stack is getting messed up by the exception. 似乎堆栈被异常搞砸了。

Here is where I got the code to generate the mini dumps. 这是我获取生成迷你转储的代码的地方。 http://blog.aaronballman.com/2011/05/generating-a-minidump/ http://blog.aaronballman.com/2011/05/generating-a-minidump/

The stack trace you posted for badFunc is perfectly fine, and the expected result, given the implementation you are using. 您为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 structure. MiniDumpWriteDump使用当前指令指针运行堆栈跟踪,除非您通过MINIDUMP_EXCEPTION_INFORMATION结构传递SEH异常的EXCEPTION_POINTERS Since the unhandled exception filter is installed at the bottom of the exception frames, calling MiniDumpWriteDump from there produces the stack trace you observed. 由于未处理的异常过滤器安装在异常帧的底部,因此从那里调用MiniDumpWriteDump会产生您观察到的堆栈跟踪。

To get a more helpful stack trace, you need to pass the EXCEPTION_POINTERS to MiniDumpWriteDump . 要获得更有用的堆栈跟踪,您需要将EXCEPTION_POINTERS传递给MiniDumpWriteDump

This is just one of many issues with the implementation you are using . 这只是您正在使用实现的许多问题之一。 There are more: 还有更多:

  • The author seems to be well aware, that they can pass nullptr for the ExceptionParam parameter, but then moves on to decide to always pass nullptr . 作者似乎很清楚,他们可以为ExceptionParam参数传递nullptr ,但随后继续决定始终传递nullptr The interface should really provide two overloads: One that takes an EXCEPTION_POINTERS argument, and one without. 接口应该真正提供两个重载:一个接受EXCEPTION_POINTERS参数,一个不接受。 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. 就目前而言, MiniDumpWriteDump在继续前进之前已经暂停了进程中的所有线程。 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. 作者未能解决一个真正的问题(两个vanilla MiniDumpWriteDump ,以及他们自己的线程挂起实现):线程在任意点被挂起。 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. 毕竟, MiniDumpWriteDump也希望从进程堆中分配内存。 The solution here is more involved: The call to MiniDumpWriteDump must be performed in its own process, with appropriate IPC in place. 这里的解决方案更为复杂:对MiniDumpWriteDump的调用必须在其自己的进程中执行,并使用适当的IPC。

Either of the above is a fairly substantial bug, and needs to be addressed. 上述任何一个都是一个相当大的bug,需要解决。 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: 如果您想在此期间实施自己的解决方案,请查看以下资源以获取可靠信息:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM