栈windows linux,Linux+Windows: 程序崩溃时,在 C++ 代码中,如何获取函数调用栈信息...

2fda6bf9384f9d4afd6d0ea436045453.png

一、前言

程序在执行过程中 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 sigactionaction;

sigemptyset(&action.sa_mask);

action.sa_sigaction = &sigHandler;

action.sa_flags = SA_SIGINFO;

for(const auto &sigPair : Signals)

{

if (sigaction(sigPair.first, &action,NULL) 

fprintf(stderr, "Error: sigaction failed! \n");

}

2. 捕获异常,获取函数调用栈信息

void sigHandler(intsignum, siginfo_t *info, void *ctx)

{

const size_t dump_size = 50;

void *array[dump_size];

intsize= backtrace(array, dump_size);

char**symbols = backtrace_symbols(array,size);

std::ostringstream oss;

for(inti = 0; i 

{

char*mangleName = 0;

char*offsetBegin = 0;

char*offsetEnd = 0;

for(char*p = symbols[i]; *p; ++p)

{

if ('('== *p)

{

mangleName = p;

}

elseif ('+'== *p)

{

offsetBegin = p;

}

elseif (')'== *p)

{

offsetEnd = p;

break;

}

}

if (mangleName && offsetBegin && offsetEnd && mangleName 

{

*mangleName++ = '\0';

*offsetBegin++ = '\0';

*offsetEnd++ = '\0';

intstatus;

char*realName = abi::__cxa_demangle(mangleName, 0, 0, &status);

if (0 == status)

oss <

else

oss <

oss <

free(realName);

}

else

{

oss <

}

}

free(symbols);

oss <

std::cout <

}

三、Windwos 平台

在 Windows 平台下的代码实现,参考了国外某个老兄的代码,如下:

1. 设置异常处理函数

#include 

#include 

SetUnhandledExceptionFilter(exceptionHandler);

2. 捕获异常,获取函数调用栈信息

void exceptionHandler(LPEXCEPTION_POINTERS info)

{

CONTEXT *context = info->ContextRecord;

std::shared_ptr RaiiSysCleaner(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_tindex= 0;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_tindex= 0;index

dump += getSymbolInfo(index, frameVector);

dump += "\n";

}

std::cout <

}

主要是利用了 StackWalk64 这个函数,从地址转换为函数名称。

利用以上几个神器,基本上可以获取到程序崩溃时的函数调用栈信息,定位问题,有如神助!

【编辑推荐】

【责任编辑:姜华 TEL:(010)68476606】

点赞 0

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/527285.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

oracle rollup分组没有数据时为0_数据库周刊19│GBASE适配鲲鹏;MySQL窗口函数;OGG双向数据同步……...

摘要&#xff1a;墨天轮数据库周刊第19期发布啦&#xff0c;每周1次推送本周数据库相关热门资讯、精选文章、干货文档。本周分享GBASE适配鲲鹏&#xff1b; 疫情激活COBOL语言&#xff1b;TiDB数据库的未来&#xff1b;Oracle与double write&#xff1b;MySQL8.0 窗口函数&…

c语言中语句作用,学习C语言的用途~

原标题&#xff1a;学习C语言的用途~C是基础的语言C语言被广泛用于操作系统和编译器的开发功能非常强虽然现在不是最流行但是最基础的东西是也比较好学的语言如:金山的创始人江明从30多岁开始学语言学的就是C对C的评价相当高C语言是一种计算机程序设计语言。它既有高级语言的特…

攻击linux的samba,Samba 中间人攻击漏洞(CVE-2015-5296)

Samba 中间人攻击漏洞(CVE-2015-5296)发布日期&#xff1a;2015-12-19更新日期&#xff1a;2016-01-01受影响系统&#xff1a;Samba Samba 4.x-4.1.22Samba Samba 4.3.x-4.3.3Samba Samba 4.2.x-4.2.7Samba Samba 3.x描述&#xff1a;CVE(CAN) ID: CVE-2015-5296Samba是在Linux…

android按钮变输入框动画,AnimShopButton 仿饿了么加入购物车旋转控件 - 自带闪转腾挪动画 的按钮。自带海量可定制 UI 属性。在 Re @codeKK Android开源站...

A shopping cart button with a telescopic displacement rotation animation ...一个仿饿了么 带伸缩位移旋转动画的购物车按钮注意&#xff0c;本控件非继承自ViewGroup,而是纯自定义 View&#xff0c;实现的仿饿了么加入购物车控件&#xff0c;自带闪转腾挪动画的按钮。图 1…

表格外粗内细怎么设置_金游艇复刻机芯-N厂灰游艇价格 | 复刻表评测

GM厂劳力游艇名仕型系列&#xff0c;官方2019年度机芯搭配全线更新为cal. 3235机芯&#xff0c;同时&#xff0c;在表盘六点位上有劳力皇冠的防伪LOGO。GM厂经历一年&#xff0c;在3135的基础上开发一体出3235机芯&#xff0c;功能与结构等完美还原于正品机芯。而且&#xff0c…

html中输出语句怎么写,javascript怎么输出?

JavaScript怎么输出&#xff1f;输出方式有哪些&#xff1f;下面本篇文章就给大家介绍JavaScript的几种输出方式&#xff0c;希望对大家有所帮助。方法1&#xff1a;使用window.alert()进行输出window.alert()方法用于显示带有一条指定消息和一个【确认】 按钮的警告框。代码示…

cron每2天跑一次_直购直测,进口新极光每2年或34000公里才需要保养一次?

我们选择以第 2 代揽胜极光P200 R-Dynamic S 车型&#xff0c;作为执行 [ 直购直测 ] 单元的第 12 辆车款&#xff0c;而在先前包含购车篇说明选择原因、油耗测试篇带大家一探具备轻油电技术的极光 P200 R-Dynamic S 油耗表现后&#xff0c;本次则是要带大家看看揽胜极光回厂定…

html中basefont标签,HTML的basefont标签

HTML 标签只有 Internet Explorer 支持 标签。应该避免使用该标签。定义和用法 ( 推荐学习&#xff1a;html教程 )标签定义基准字体。该标签可以为文档中的所有文本定义默认字体颜色、字体大小和字体系列。HTML 与 XHTML 之间的差异在 HTML 4.01 中&#xff0c;不赞成使用 ba…

linux mv 保持目录结构_(三)Linux系统目录结构

点击蓝字 关注我们Linux系统目录结构&#xff1a;所有的类Unix系统根分区下的文件系统都基本一致。分别介绍一下功能&#xff1a;/bin&#xff1a;所有常用的可执行的二进制文件&#xff0c;就是“命令”&#xff0c;这些命令是所有用户都可以使用的。(存放系统命令的目录&…

d3.js html显示图片,d3.js v4:如何在鼠标点击节点后显示图像

在使用d3.js时仍然相当缺乏经验&#xff0c;我碰到了一个障碍。 希望有人能帮助我。d3.js v4&#xff1a;如何在鼠标点击节点后显示图像我试图在鼠标单击图形中的节点时显示图片。 理想情况下&#xff0c;我想单击几个节点并显示图像。双击节点应该删除图像。点击背景将删除所有…

语言速算24点的小窍门_4秒钟1道题!12岁少年三夺24点大赛冠军

数学文化节上&#xff0c;参加大赛的孩子们。夺得24点大赛冠军的华跃麟。本报讯 (重庆晨报上游新闻记者 秦健)“哇&#xff0c;太厉害了。”“快快快&#xff0c;超过他们俩了&#xff01;”昨天下午&#xff0c;“第二届重庆数学文化节”在重庆市德普外国语学校体育活动中心举…

用计算机表白我不喜欢你了,隐藏式表白,表白不一定要用“我喜欢你”这几个字...

要知道女生都是喜欢浪漫的&#xff0c;浪漫不失为一种提升表白成功率的方式。但表白的时候&#xff0c;如果只是一束鲜花&#xff0c;一句简单“我喜欢你”&#xff0c;难免显得太过乏味&#xff0c;而且不够浪漫。那该怎么给表白添加一点新意和浪漫呢?下面&#xff0c;是小编…

切片分析报告格式_社科论文写作101-APA数据分析结果报告格式

什么比写论文更惨&#xff1f;改论文&#xff01;&#xff01;特别是搞量化数据的&#xff0c;少个数据或报告格式不正确的话&#xff0c;重新搞数据和格式吧——又要打开spss&#xff0c;又要在网上看数据分析步骤&#xff0c;又要在熟悉的word界面花上一天。所以&#xff0c;…

如何关闭借呗订阅开通通知_支付宝花呗借呗隐藏规则,芝麻分600以上,花呗3.6万,借呗12万!...

阅读本文前&#xff0c;请您先点击上面的“蓝色字体”&#xff0c;再点击“关注”&#xff0c;这样您就可以继续免费收到文章了。每天都有分享&#xff0c;完全是免费订阅&#xff0c;请放心关注。 注&#xff1a;本文转载自网络,侵删经常遇到网友反馈&#xff0c;…

骁龙660是32位还是64位_微软公布v2004最低处理器要求,放弃32位系统,你的CPU还能支持吗?...

最近关于win10 20H1&#xff08;win10更新五月版&#xff09;的消息铺天盖地席卷而来&#xff0c;据说只有开发者用户可以先行在MSDN订阅网站下载该版本的ISO镜像文件&#xff0c;对于主流消费者而言&#xff0c;预计要再煎熬等到28日。而且微软也提前更新支持文档&#xff0c;…

中石油《计算机应用基础》,2017中国石油大学《计算机应用基础》第3阶段在线作业.doc...

2017中国石油大学《计算机应用基础》第3阶段在线作业.doc (23页)本资源提供全文预览&#xff0c;点击全文预览即可全文预览,如果喜欢文档就下载吧&#xff0c;查找使用更方便哦&#xff01;19.90 积分&#xfeff;窗体顶端1(2.0分)在Excel2010的工作表中&#xff0c;假定C3:C8区…

产品战略规划十步法ppt_从管理咨询角度谈如何系统地做产品战略规划?

来源&#xff1a;知乎作者&#xff1a;柚先生&#xff0c;著作权归作者所有。一个优秀的PM必须系统掌握与产品相关的知识和技能&#xff0c;本文结合了笔者工作以来的收获与最近研读的《产品心经》和《金字塔原理》&#xff0c;分享一套做战略规划的系统思维和方法论(同时适用于…

计算机用鼠标画图,实现鼠标在电脑上画画

鼠标的功能多种多样你知道怎么用鼠标画画吗?不知道的话跟着学习啦小编一起来学习怎么用鼠标画画。鼠标在电脑上画画的步骤首先打开国际上使用比较受欢迎的漫画和插画类绘图软件SAI&#xff0c;然后CTRLN新建一个文件&#xff0c;并使用软件右边工具栏的油漆桶&#xff0c;点选…

c# opencv 轮廓检测_基于OpenCV的区域分割、轮廓检测和阈值处理

OpenCV是一个巨大的开源库&#xff0c;广泛用于计算机视觉&#xff0c;人工智能和图像处理领域。它在现实世界中的典型应用是人脸识别&#xff0c;物体检测&#xff0c;人类活动识别&#xff0c;物体跟踪等。现在&#xff0c;假设我们只需要从整个输入帧中检测到一个对象。因此…

斑马888t打印机墨盒安装_硒鼓?墨盒?究竟哪个才是打印机的“灵魂伴侣”?...

硒鼓和墨盒是当代打印机完成打印必不可少的配件&#xff0c;在打印过程中&#xff0c;如果没有这两样&#xff0c;那么打印机将无法启动&#xff0c;打印不出任何东西。但同样作为可以让打印机成像的东西&#xff0c;这二者之间也有着很大的区别。而今天&#xff0c;墨弘办公耗…