菜鸟笔记
提升您的技术认知

C++抛异常时如何获取堆栈调用信息

问题背景

一般来说,我们使用第三方代码的时候,不可避免的会遇到异常信息。例如调用错误,库中会抛出异常。经常是由于上下文日志不足,我们只能看到catch处的日志,而不清楚异常是哪些函数调用导致。这导致定位问题比较麻烦,经常要花比较长时间去跟进。去网上找了些资料,

解决方案

方案一:感觉最简单的,还是借助GDB工具,用catch throw命令来帮忙找问题所在。具体的实施方案可以参考这个链接:https://www.digitalpeer.com/blog/find-where-a-cpp-exception-is-thrown

我把原文coyp过来,如下:

//Here's an example throw_exception.cpp.

#include <iostream>
#include <stdexcept>

using namespace std;

void function()
{
   throw runtime_error("i am an exception");
}

int main()
{
   try
   {
      function();
   }
   catch(const std::exception& e)
   {
      cout << e.what() << endl;
   }

   return 0;
}

The makefile for it.

all: throw_exception

throw_exception : throw_exception.cpp
$(CXX) -g $< -o $@

Here's how to use catch throw in gdb.

~/exception$ make
g++ -g throw_exception.cpp -o throw_exception
~/exception$ gdb throw_exception
...
Reading symbols from throw_exception...done.
(gdb) catch throw
Catchpoint 1 (throw)
(gdb) run
Starting program: throw_exception
Catchpoint 1 (exception thrown), 0x00007ffff7b8f910 in __cxa_throw () from /usr/lib/libstdc++.so.6
(gdb) where
#0 0x00007ffff7b8f910 in __cxa_throw () from /usr/lib/libstdc++.so.6
#1 0x0000000000400d89 in function () at throw_exception.cpp:8
#2 0x0000000000400dca in main () at throw_exception.cpp:15
(gdb)

方案二:如果是自己写的代码,在抛出异常的时候,可以借助backtrace函数,获取当前进程调用堆栈的相关信息,进而输出到日志中帮助定位问题。具体的实施方案可以参考这个链接:

https://www.gnu.org/software/libc/manual/html_node/Backtraces.html

如果第三方库,那目前能想到的还是使用方案一。方案二的问题在于,无法对第三方库的抛异常时,把自己的代码挂进去执行。