在C++ 代码中怎么获取函数调用栈信息
发表于:2025-02-23 作者:千家信息网编辑
千家信息网最后更新 2025年02月23日,这篇文章主要介绍"在C++ 代码中怎么获取函数调用栈信息",在日常操作中,相信很多人在在C++ 代码中怎么获取函数调用栈信息问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答
千家信息网最后更新 2025年02月23日在C++ 代码中怎么获取函数调用栈信息
这篇文章主要介绍"在C++ 代码中怎么获取函数调用栈信息",在日常操作中,相信很多人在在C++ 代码中怎么获取函数调用栈信息问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"在C++ 代码中怎么获取函数调用栈信息"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
一、前言
程序在执行过程中 crash 是非常严重的问题,一般都应该在测试阶段排除掉这些问题,但是总会有漏网之鱼被带到 release 阶段。
因此,程序的日志系统需要侦测这种情况,在代码崩溃的时候获取函数调用栈信息,为 debug 提供有效的信息。
二、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 << "\tstack dump [" << i << "] " << symbols[i] << " : " << realName << "+"; else oss << "\tstack dump [" << i << "] " << symbols[i] << mangleName << "+"; oss << offsetBegin << offsetEnd << std::endl; free(realName); } else { oss << "\tstack dump [" << i << "] " << symbols[i] << std::endl; } } free(symbols); oss << std::endl; std::cout << oss.str(); // 打印函数调用栈信息 }
三、Windwos 平台
在 Windows 平台下的代码实现,参考了国外某个老兄的代码,如下:
1. 设置异常处理函数
#include#include SetUnhandledExceptionFilter(exceptionHandler);
2. 捕获异常,获取函数调用栈信息
void exceptionHandler(LPEXCEPTION_POINTERS info) { CONTEXT *context = info->ContextRecord; std::shared_ptrRaiiSysCleaner(nullptr, [&](void *) { SymCleanup(GetCurrentProcess()); }); const size_t dumpSize = 64; std::vector frameVector(dumpSize); DWORD machine_type = 0; STACKFRAME64 frame = {}; frame.AddrPC.Mode = AddrModeFlat; frame.AddrFrame.Mode = AddrModeFlat; frame.AddrStack.Mode = AddrModeFlat; #ifdef _M_IX86 frame.AddrPC.Offset = context->Eip; frame.AddrFrame.Offset = context->Ebp; frame.AddrStack.Offset = context->Esp; machine_type = IMAGE_FILE_MACHINE_I386; #elif _M_X64 frame.AddrPC.Offset = context->Rip; frame.AddrFrame.Offset = context->Rbp; frame.AddrStack.Offset = context->Rsp; machine_type = IMAGE_FILE_MACHINE_AMD64; #elif _M_IA64 frame.AddrPC.Offset = context->StIIP; frame.AddrFrame.Offset = context->IntSp; frame.AddrStack.Offset = context->IntSp; machine_type = IMAGE_FILE_MACHINE_IA64; frame.AddrBStore.Offset = context.RsBSP; frame.AddrBStore.Mode = AddrModeFlat; #else frame.AddrPC.Offset = context->Eip; frame.AddrFrame.Offset = context->Ebp; frame.AddrStack.Offset = context->Esp; machine_type = IMAGE_FILE_MACHINE_I386; #endif for (size_t index = 0; index < frameVector.size(); ++index) { if (StackWalk64(machine_type, GetCurrentProcess(), GetCurrentThread(), &frame, context, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL)) { frameVector[index] = frame.AddrPC.Offset; } else { break; } } std::string dump; const size_t kSize = frameVector.size(); for (size_t index = 0; index < kSize && frameVector[index]; ++index) { dump += getSymbolInfo(index, frameVector); dump += "\n"; } std::cout << dump; }
主要是利用了 StackWalk64 这个函数,从地址转换为函数名称。
到此,关于"在C++ 代码中怎么获取函数调用栈信息"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!
函数
信息
代码
C++
信号
处理
学习
平台
问题
更多
程序
阶段
帮助
实用
有效
接下来
漏网之鱼
信号处理
前言
名称
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
广东节能软件开发业务
数据库db是什么意思
呼和浩特网络技术公司招聘
网络技术处理四代好不好
居委会网络安全宣传周方案
图文软件开发公司
web服务器主机地址的范围
深圳市云之讯网络技术有限
四川物保宝网络技术有限公司
c# 如何编写数据库
北大互联网彭波数字科技
互联网科技卫生巾
爱思助手 全恢复数据库
服务器编译线
风湿科数据库
构筑网络安全四梁八柱
天津企业软件开发服务诚信互利
网络安全知识手抄报 学生
2020年低功耗服务器cpu
山东网络技术转让热线
直销双轨制软件开发
网络技术处理四代好不好
河北超融合服务器厂家虚拟主机
三级网络技术划分子网
广州热带雨林网络技术
安全性数据库药物警戒
我的世界如何将服务器存档导出
云服务器添加域名
开源数据库的上市公司
成都长荣网络技术有限公司介绍