这篇文章主要讲述在 Linux 和 Windows 这 2 个平台上,如何用C++ 来捕获函数调用栈里的信息。
一、前言
程序在执行过程中 crash 是非常严重的问题,一般都应该在测试阶段排除掉这些问题,但是总会有漏网之鱼被带到 release 阶段。
因此,程序的日志系统需要侦测这种情况,在代码崩溃的时候获取函数调用栈信息,为 debug 提供有效的信息。
这篇文章的理论知识很少,直接分享 2 段代码:在 Linux 和 Windows 这 2 个平台上,如何用C++ 来捕获函数调用栈里的信息。
二、Linux 平台
1. 注册异常信号的处理函数 需要处理哪些异常信号
#include #include #include const std::map Signals = { {SIGINT, "SIGINT"}, {SIGABRT, "SIGABRT"}, {SIGFPE, "SIGFPE"}, {SIGILL, "SIGILL"}, {SIGSEGV, "SIGSEGV"} // 可以添加其他信号 };
注册信号处理函数
struct sigaction action; sigemptyset(&action.sa_mask); action.sa_sigaction = &sigHandler; action.sa_flags = SA_SIGINFO; for (const auto &sigPair : Signals) { if (sigaction(sigPair.first, &action, NULL) < 0) fprintf(stderr, "Error: sigaction failed! \n"); }
2. 捕获异常,获取函数调用栈信息
void sigHandler(int signum, siginfo_t *info, void *ctx) { const size_t dump_size = 50; void *array[dump_size]; int size = backtrace(array, dump_size); char **symbols = backtrace_symbols(array, size); std::ostringstream oss; for (int i = 0; i < size; ++i) { char *mangleName = 0; char *offsetBegin = 0; char *offsetEnd = 0; for (char *p = symbols[i]; *p; ++p) { if ('(' == *p) { mangleName = p; } else if ('+' == *p) { offsetBegin = p; } else if (')' == *p) { offsetEnd = p; break; } } if (mangleName && offsetBegin && offsetEnd && mangleName < offsetBegin) { *mangleName++ = '\0'; *offsetBegin++ = '\0'; *offsetEnd++ = '\0'; int status; char *realName = abi::__cxa_demangle(mangleName, 0, 0, &status); if (0 == status) oss关注打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?