Qt C ++未处理的异常堆栈跟踪 [英] Qt C++ Unhandled exceptions stack trace

查看:839
本文介绍了Qt C ++未处理的异常堆栈跟踪的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试找出一种方法,以在发生崩溃时获取已部署的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 非常好,并且给定您正在使用的实现的预期结果。 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 the ExceptionParam parameter, but then moves on to decide to always pass nullptr. The interface should really provide two overloads: One that takes an EXCEPTION_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 to MiniDumpWriteDump 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆