在应用程序崩溃/C++ 期间获取堆栈跟踪

Posted

技术标签:

【中文标题】在应用程序崩溃/C++ 期间获取堆栈跟踪【英文标题】:get stacktrace during an application crash - c/c++ 【发布时间】:2016-05-19 15:14:36 【问题描述】:

我是一名尝试编写 C-C++ 代码的 Java 开发人员。 基本上我有一些构建脚本,它使用 Visual Studio 组件来构建应用程序库 - dll。我们不使用 Visual Studio IDE 进行调试。

但是每当我们的应用程序遇到崩溃时,我们必须逐行输入调试语句,并且需要检查崩溃的确切代码行。

C/C++ 中是否有任何 API 可以在程序崩溃期间将堆栈跟踪写入文件?

在程序退出期间调用的某种事件侦听器,可以将堆栈跟踪和错误信息打印到日志文件中。

我已经看到了很多与此相关的问题,但我无法通过代码而不是调试工具来处理这个问题。我觉得 Java 在错误处理方面非常先进。

提前致谢!

【问题讨论】:

在调试器中运行它,您可以从中获取堆栈跟踪。 您不使用 Visual Studio IDE 进行调试是一种耻辱,因为 i 可以说是世界上最好的用户模式 ​​Windows 程序调试器。在紧要关头,您可以只使用 WinDbg,它确实比 Visual Studio 更健壮且功能丰富,但代价是使用起来相当更复杂(但如果你超过了它,它可以做一些了不起的事情)。 【参考方案1】:

标准没有为此提供任何便利。也就是说,您可以使用特定于操作系统的 API 来获得您想要的东西。在 Windows 上,最简单的可能是使用StackWalker。你确实需要自己处理 SEH 的怪事。我建议this article 了解更多信息。

在 POSIX 平台上,您可以使用 glibc 中的 backtrace 函数。

一般来说,两者都需要使用调试信息编译您的程序。也可以创建不带符号名称的故障转储(请参阅 Windows 上的 Minidumps),但您需要对它们进行解码(例如,Visual Studio 为您做了,但您在帖子中提到您不使用它)。

另外,请记住,从崩溃的进程编写崩溃转储非常容易出错(因为您真的不知道当时您的应用程序处于什么状态)。如果您从另一个进程编写故障转储,您可能会获得更可靠的结果。之前我整理了一个简单的 example out-of-process crash handler 来演示如何实现它。

【讨论】:

【参考方案2】:

您可以使用std::set_terminate 定义当异常离开main() 时要调用的函数,另外您可以为 SIGSEGV 安装信号处理程序以捕获分段错误。

您可以使用 libunwind (http://www.nongnu.org/libunwind/) 或使用 libc 中的 backtrace() 函数获取堆栈跟踪(在 Linux 上)。

我有时在自己的异常类中做的一件事是在构造函数中抓取并存储堆栈跟踪,然后我可以获取捕获异常的位置并打印异常抛出位置的跟踪。

【讨论】:

【参考方案3】:

您可以在 C 中使用 <errno.h> 来处理您的错误并将它们记录到日志文件中。错误的标准通量是stderr

获得错误的一种解决方案是使用<errno.h> 中包含的函数perror,它将显示确切的错误。

要使用它,请将其放入错误捕获器中。

if (!fileIsOpen())
   perror("File not opened");

希望对你有帮助。

【讨论】:

以上是关于在应用程序崩溃/C++ 期间获取堆栈跟踪的主要内容,如果未能解决你的问题,请参考以下文章

如何使用映射文件对 Android 堆栈跟踪进行去混淆处理

Android 阻止用户对应用程序进行堆栈跟踪

我的程序崩溃时如何自动生成堆栈跟踪

在 C# 中如何收集程序崩溃的堆栈跟踪

符号化没有崩溃日志的 iOS 崩溃堆栈跟踪

没有有用的堆栈跟踪的 Android 应用程序崩溃