windows 如何从崩溃中提取调试信息

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/850617/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 12:27:31  来源:igfitidea点击:

How to extract debugging information from a crash

c++windowscrashstack-tracebacktrace

提问by hoju

If my C++ app crashes on Windows I want to send useful debugging information to our server.

如果我的 C++ 应用程序在 Windows 上崩溃,我想将有用的调试信息发送到我们的服务器。

On Linux I would use the GNU backtrace()function - is there an equivalent for Windows?

在 Linux 上,我会使用 GNUbacktrace()函数 - 是否有 Windows 的等效函数?

Is there a way to extract useful debugging information after a program has crashed? Or only from within the process?

有没有办法在程序崩溃后提取有用的调试信息?还是仅从流程内部?

(Advice along the lines of "test you app so it doesn't crash" is not helpful! - all non-trivial programs will have bugs)

(“测试您的应用程序使其不会崩溃”的建议没有帮助! - 所有非平凡的程序都会有错误)

采纳答案by Michael

The function Stackwalk64can be used to snap a stack trace on Windows.

函数Stackwalk64可用于在 Windows 上捕捉堆栈跟踪。

If you intend to use this function, you should be sure to compile your code with FPO disabled - without symbols, StackWalk64 won't be able to properly walk FPO'd frames.

如果你打算使用这个函数,你应该确保在禁用 FPO 的情况下编译你的代码 - 如果没有符号,StackWalk64 将无法正确地遍历 FPO 的帧。

You can get some code running in process at the time of the crash via a top-level __try/__exceptblock by calling SetUnhandledExceptionFilter. This is a bit unreliable since it requires you to have code running inside a crashed process. Alternatively, you can just the built-in Windows Error Reporting to collect crash data. This is more reliable, since it doesn't require you to add code running inside the compromised, crashed process. The only cost is to get a code-signing certificate, since you must submit a signed binary to the service. https://sysdev.microsoft.com/en-US/Hardware/signup/has more details.

__try/__except通过调用 SetUnhandledExceptionFilter,您可以通过顶级块在崩溃时让一些代码在进程中运行。这有点不可靠,因为它要求您在崩溃的进程中运行代码。或者,您可以仅使用内置的 Windows 错误报告来收集崩溃数据。这更可靠,因为它不需要您添加在受感染、崩溃的进程中运行的代码。唯一的成本是获得代码签名证书,因为您必须向服务提交一个签名的二进制文件。 https://sysdev.microsoft.com/en-US/Hardware/signup/有更多细节。

回答by Stephen Nutt

You can use the Windows API call MiniDumpWriteDumpif you wish to roll your own code. Both Windows XP and Vist automate this process and you can sign up at https://winqual.microsoft.comto gain access to the error reports.

如果您希望推出自己的代码,可以使用 Windows API 调用MiniDumpWriteDump。Windows XP 和 Vist 都会自动执行此过程,您可以在https://winqual.microsoft.com上注册以访问错误报告。

Also check out http://kb.mozillazine.org/Breakpadand http://www.codeproject.com/KB/debug/crash_report.aspxfor other solutions.

还可以查看http://kb.mozillazine.org/Breakpadhttp://www.codeproject.com/KB/debug/crash_report.aspx以获取其他解决方案。

回答by RED SOFT ADAIR

Its quite simple to dump the current stackframe addresses into a log file. All you have to do is get such a function called on program faults (i.e. a interrupt handler in Windows) or asserts. This can be done at released versions as well. The log file then can be matched with a map file resulting in a call stack with function names.

将当前堆栈帧地址转储到日志文件中非常简单。您所要做的就是获得这样一个在程序错误时调用的函数(即 Windows 中的中断处理程序)或断言。这也可以在发布版本中完成。然后可以将日志文件与映射文件进行匹配,从而产生带有函数名称的调用堆栈。

I published a article about this some years ago.

几年前我发表了一篇关于这个的文章。

See http://www.ddj.com/architect/185300443

http://www.ddj.com/architect/185300443

回答by Ben Straub

Generate a minidump file. You can then load it up in windbgor Visual Studio and inspect the entire stack where the crash occurred.

生成一个小型转储文件。然后,您可以在windbgVisual Studio 或 Visual Studio 中加载它并检查发生崩溃的整个堆栈。

Here'sa good place to start reading.

这是开始阅读的好地方。

回答by Marineio

This website provides quite a detailed overview of stack retrieval on Win32 after a C++ exception:

这个网站提供了一个 C++ 异常后在 Win32 上堆栈检索的详细概述:

http://www.eptacom.net/pubblicazioni/pub_eng/except.html

http://www.eptacom.net/pubblicazioni/pub_eng/except.html

Of course, this will only work from within the process, so if the process gets terminated or crashes to the point where it terminates before that code is run, it won't work.

当然,这只能在进程内工作,所以如果进程被终止或崩溃到它在代码运行之前终止的点,它就不会工作。

回答by Ryan Ginstrom

Let me describe how I handle crashes in my C++/WTL application.

让我描述一下我如何处理 C++/WTL 应用程序中的崩溃。

First, in the main function, I call _set_se_translator, and pass in a function that will throw a C++ exception instead of using structured windows exceptions. This function gets an error code, for which you can get a Windows error message via FormatMessage, and a PEXCEPTION_POINTERS argument, which you can use to write a minidump (code here). You can also check the exception code for certain "meltdown" errors that you should just bail from, like EXCEPTION_NONCONTINUABLE_EXCEPTION or EXCEPTION_STACK_OVERFLOW :) (If it's recoverable, I prompt the user to email me this minidump file.)

首先,在主函数中,我调用_set_se_translator,并传入一个将抛出 C++ 异常而不是使用结构化窗口异常的函数。此函数获取错误代码,您可以通过FormatMessage获取 Windows 错误消息和 PEXCEPTION_POINTERS 参数,您可以使用它来编写小型转储(代码在这里)。您还可以检查异常代码是否存在您应该避免的某些“崩溃”错误,例如 EXCEPTION_NONCONTINUABLE_EXCEPTION 或 EXCEPTION_STACK_OVERFLOW :)(如果它是可恢复的,我会提示用户通过电子邮件将这个小型转储文件发送给我。)

The minidump file itself can be opened in Visual Studio like a normal project, and providing you've created a .pdb file for your executable, you can run the project and it'll jump to the exact location of the crash, together with the call stack and registers, which can be examined from the debugger.

小型转储文件本身可以像普通项目一样在 Visual Studio 中打开,如果您已经为可执行文件创建了一个 .pdb 文件,您可以运行该项目,它会跳转到崩溃的确切位置,以及调用堆栈和寄存器,可以从调试器中检查。

回答by gbjbaanb

If you want to grab a callstack (plus other good info) for a runtime crash, on a release build even on site, then you need to set up Dr Watson(run DrWtsn32.exe). If you check the 'generate crash dumps' option, when an app crashes, it'll write a mini dump file to the path specified (called user.dmp).

如果您想获取运行时崩溃的调用堆栈(以及其他好的信息),甚至在现场发布版本上,那么您需要设置Dr Watson(运行 DrWtsn32.exe)。如果您选中“生成崩溃转储”选项,当应用程序崩溃时,它会将一个小型转储文件写入指定的路径(称为 user.dmp)。

You can take this, combine it with the symbols you created when you built your server (set this in your compiler/linker to generate pdb files - keep these safe at home, you use them to match the dump so they can work out the source where the crash occurred)

您可以将其与构建服务器时创建的符号结合使用(在编译器/链接器中设置它以生成 pdb 文件 - 将这些文件放在家里,您可以使用它们来匹配转储,以便他们可以计算出源崩溃发生的地方)

Get yourself windbg, open it and use the menu option to 'load crash dump'. Once it's loaded everything you can type '~#kp' to get a callstack for every thread (or click the button at the top for the current thread).

获取自己的windbg,打开它并使用菜单选项来“加载故障转储”。加载完所有内容后,您可以键入“~#kp”以获取每个线程的调用堆栈(或单击当前线程顶部的按钮)。

There's good articles to know how to do this all over the web, This oneis my favourite, and you'll want to read thisto get an understanding of how to helpyourself manage the symbols really easily.

网络上有很多很好的文章可以了解如何执行此操作,是我的最爱,您需要阅读本文以了解如何帮助自己轻松管理符号。

回答by Canopus

You will have to set up a dump generation framework in your application, hereis how you may do it.

您必须在您的应用程序中设置一个转储生成框架,是您可以这样做的方法。

You may then upload the dump file to the server for further analysis using dump analyzers like windbg.

然后,您可以将转储文件上传到服务器,以便使用诸如 windbg 之类的转储分析器进行进一步分析。

回答by user351580

You may want to use adplus to capture the crash callstack.

您可能希望使用 adplus 来捕获崩溃调用堆栈。

You can download and install Debugging tools for Windows.

您可以下载并安装适用于 Windows 的调试工具。

Usage of adplus is mentioned here: Adplus usage

这里提到了adplus的用法: Adplus用法

This creates the complete crash or hang dump. Once you have the dump, Windbg comes to the rescue. Map the correct pdbs and symbols and you are all set to analyze the dump. To start with use the command "!analyze -v"

这会创建完整的崩溃或挂起转储。一旦你有了转储,Windbg 就会来救援。映射正确的 pdbs 和符号,您就可以分析转储了。首先使用命令“!analyze -v”