前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >日更系列:排查一次gcc的复杂core

日更系列:排查一次gcc的复杂core

原创
作者头像
mariolu
修改于 2022-05-14 06:32:51
修改于 2022-05-14 06:32:51
1.1K00
代码可运行
举报
运行总次数:0
代码可运行

线上服务出现了重启告警,而且重启后继续。排查线上出现了一堆core,core信息显示如下:

这个是一个线程抛出的异常,但是看不到线程本身的代码,只可看到core文件堆栈栈钉出现在libstdc++库上。唯一业务代码在第6个栈帧。catch方块里的throw e代码上。

这里有几个问题。这里的异常实际上是在线程调度的函数抛出了异常。也就是thread->m_Runner->Execute()的时候,当时在异常抛出的时候,我们其实想要看到的是那个时候的堆栈内存快照。但是这个core发生的时候,已经退出了那个Execute函数,这个实际函数已经退出了,当时core点的堆栈已经展开了。然后函数跳过Execute函数,走到catch模块,到throw e位置,由于外部再无补货这个exception e的函数,函数在此结束。core信息反应的是此时throw e的内存快照。

1. 问题

1.1 c++的throw或者abort机制

这里引入了一个知识点就是:C++ 程序,如果 代码throw了 exception ,但是外部又没有 catch,那么一般会产生 coredump。而如果外面catch住了异常,这个就不会产生coredump,但是你也可以继续选择向上级抛异常,也可以忽略打点异常日志出来e.what()。 gcc有个宏_GLIBCXX_THROW_OR_ABORT定义你的行为是throw还是abort

我记得谷歌c++规范也是建议大家不写异常。但是如果团队内有人不遵守怎么办,我们可以在makefile加上(-gcc的 -fno-exceptions ,在编译阶段禁用异常机制。这样写了异常的代码不会通过。

gcc有个宏_GLIBCXX_THROW_OR_ABORT 的宏,該宏定義為

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#ifndef _GLIBCXX_THROW_OR_ABORT
# if __cpp_exceptions
#  define _GLIBCXX_THROW_OR_ABORT(_EXC) (throw (_EXC))
# else
#  define _GLIBCXX_THROW_OR_ABORT(_EXC) (__builtin_abort())
# endif
#endif

1.2 线程执行机制

有了第一个问题的铺垫,我们知道上层代码如果catch住了调用函数的异常,会导致core信息显示的不是调用函数本身的堆栈。所以要么函数外面不cacth,要么让抛__cxa_throw的函数直接挂掉。

本文的第一个问题正是,在 gcc 4.x 版本(gcc version 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) )产生的 coredump 文件中,没有 throw 时候的堆栈信息,导致不知道是哪里 throw 的,没法查问题。

我们继续看gcc 4.x 的 /libstdc++-v3/src/c++11/thread.cc:92 的代码就发现原因。这个gcc 4.x的线程执行的实现里面有个 catch(…),所以 stack unwind 了,就没了 throw 时候的 stack 。

以下是gcc4.x-6.x的实现

而gcc7.x以上已经重新实现了,以下是gcc 7.x以上的实现

这里就没有了cache。https://abcdabcd987.com/libstdc++-bug/

二、解决办法

2.1 升级到gcc7以上

一个解决办法是可以升级 GCC 7 ,

2.2 强行改写throw方法

因为不是所有的项目都方便切换到新版本的gcc,历史代码不好兼容新版本gcc,可以用更简单的办法:

1.代码 hook __cxa_throw

一个解决办法是通过改代码,hook __cxa_throw() 让每次生成的 coredump 都带上堆栈:

https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/libsupc%2B%2B/cxxabi.h#L616

vim /usr/include/c++/4.8.2/cxxabi.h 看到__cxa_throw的声明。__cxa_throw() 是 libstdc++/libc++ 用于实现 throw 的函数。

https://libcxxabi.llvm.org/spec.html

我们可以重写(或者叫hook)

这个函数要加到你调用线程的那个文件里。比如我这里的Util/CThread.cpp(项目代码中线程执行函数)。

效果如下:

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
怎样让 C++ 中 throw exception 产生的 coredump 带上栈
一个 C++ 程序,如果 throw 了 exception ,但是又没有 catch,那么一般会产生 coredump, 问题是,在 gcc 4.x 版本产生的 coredump 文件中,没有 throw 时候的堆栈信息,导致不知道是哪里 throw 的,没法查问题。
byronhe
2021/06/25
2.2K0
一剑破万法:noexcept与C++异常导致的coredump
作为C/C++程序员,最不想见到的就是coredump。coredump的原因有很多,今天我只谈其中的一种,那就是由于异常没有被catch导致的coredump。这是十分常见的一大的coredump原因,尤其是在大型C++在线服务中。
果冻虾仁
2023/02/25
2.1K0
一剑破万法:noexcept与C++异常导致的coredump
从Xcode10不再支持libstdc++说起
众所周知从Xcode10起,苹果摒弃了对libstdc++库的支持转而支持libc++库了。这两个库在Xcode9甚至更早的版本就已经同时存在于系统中并且可供开发者选择,当然在Xcode9时代苹果就已经宣布了将要废弃libstdc++的信息了。
欧阳大哥2013
2018/11/09
2.3K0
记一次线上崩溃问题的排查过程
由于正值双十一期间,业务以稳定为主,线上服务崩溃,这可不是一件小事,赶紧登陆线上服务器,分析原因,迅速解决。
高性能架构探索
2022/08/25
1.5K0
记一次线上崩溃问题的排查过程
日更系列:如果gdb打印不出std容器怎么办
c++中我们经常会使用gdb来截获进程,进行单步调试然后打印出过程中的数据供分析。但是有时候在系统出并不能很好打印出std容器的数据。std比如说一些容器是用红黑树实现,但是打印出红黑树原始结构,这并不是我们想要的东西。
mariolu
2021/12/26
1.9K1
深入浅出理解DeepSeek 3FS (3) 步步引导轻松理解内存管理,面试必看
工作8年的小王 同学 为了准备c++面试, 很早 就从脉脉上搜索过类似题目,信心满满而去, 什么返回值区别,重载区别?还有函数用法区别?
早起的鸟儿有虫吃
2025/04/11
960
深入浅出理解DeepSeek 3FS (3) 步步引导轻松理解内存管理,面试必看
踩坑一处(GCC)STL `std::async` 实现BUG导致的crash问题
近期发现项目组使用新版本的 opentelemetry-cpp 的时候偶现崩溃。崩溃的位置在STL的 std::future 析构的地方,而这个 std::future 由 std::async创建。 比较违反直觉,这里记录分享一下分析和解决过程方面其他碰到的小伙伴们。
owent
2024/07/23
2750
gccc如何处理static变量初始化
局部变量在C++中的使用要频繁的多,并且功能也强大的多,但是这些强大功能的背后无疑会引入问题的复杂性,不想让马儿吃草只想让马儿跑的事大家表乱想。这些初始化的实现就需要C++的库执行更多的动作来完成,虽然各种编译器都是像如今开展的“学雷锋”活动一样干了很多好事都没有留名,但是作为一个程序员,还是要对别人的贡献进行表彰。 我们看一下下面的一段代码,本文将会围绕这个代码进行展开,可以看到这个简单的程序,让C++生成了非常多的代码让人应接不暇
thierryzhou
2022/12/01
7800
故障分析 | MySQL 设置 terminology_use_previous 参数导致数据库 Crash
由于安全因素,客户需要将 MySQL 升级到 8.0.26 版本,但由于 8.0.26 的一些术语的不兼容性变更,对于监控采集的工具/程序会出现异常,针对这个情况,MySQL 官方也提供了解决方案,那就是新增了一个参数terminology_use_previous,当将该参数设置为BEFORE_8_0_26时,可以保持 8.0.26 版本之前的术语形式,如依旧保持 master,slave 的术语形式,以下是官方文档 8.0.26 release note 的描述片段摘要:
爱可生开源社区
2022/02/09
8240
故障分析 | MySQL 设置 terminology_use_previous 参数导致数据库 Crash
日更系列 - 又一次碰到非线程安全std容器的core
众所周知,std容器是非线程安全的,跟非线程安全的容器,如果代码core掉,通常会在容器的一些方法函数中。因为这类的core文件往往显示不是很直观,很多c++ std新手往往对这类型core无从下手。所以这里做一些纪录以总结通用经验给后人享用。
mariolu
2022/06/02
1.1K0
C++ 内存管理(一)
在编程时可以通过上图的几种方法直接或间接地操作内存。下面将介绍四种C++内存操作方法:
公众号guangcity
2019/09/20
1.6K0
C++ 内存管理(一)
GDB调试-从入门实践到原理
在上篇文章中,我们分析了线上coredump产生的原因,其中用到了coredump分析工具gdb,这几天一直有读者在问,能不能写一篇关于gdb调试方面的文章,今天借助此文,分享一些工作中的调试经验,希望能够帮到大家。
高性能架构探索
2022/08/25
3.2K0
GDB调试-从入门实践到原理
日更系列之如何快速排查protobuf数据格式
之前和同事定义一个pb数据格式问题,他那边负责生产数据源,然后转pb再存到redis,然后我来消费这个pb,进行解开。这个过程不涉及到数据压缩如snappy。首先我消费线程代码写好了,来和他联调这份数据。但是我这边代码解析失败了。
mariolu
2022/03/01
1.6K0
C++ STL源码剖析之双向环形链表list
双向环状链表从节点值为3开始插入,红色框表示最后一个节点(end()指向的节点)。黄色线条表示指向前驱节点,黑色线条表示指向后继节点。
公众号guangcity
2019/10/09
1.6K0
C++内存问题排查攻略
GCC提供了-fstack-usage选项,能输出每个函数栈的最大使用量。开启后,为每个编译目标创建.su文件,每行包括函数名、字节数、修饰符(static/dynamic/bounded)中的一个或多个。修饰符的含义如下:
腾讯技术工程官方号
2024/08/14
3840
C++内存问题排查攻略
得物 Android Crash 治理实践
通过修复历史遗留的Crash漏报问题(包括端侧SDK采集的兼容性优化及Crash平台的数据消费机制完善),得物Android端的Crash监控体系得到显著增强,使得历史Crash数据的完整捕获能力得到系统性改善,相应Crash指标也有所上升,经过架构以及各团队的共同努力下,崩溃率已从最高的万2降至目前的万1.1到万1.5,其中疑难问题占比约90%、因系统bug导致的Crash占比约40%,在本文中将简要介绍一些较典型的系统Crash的治理过程。
得物技术
2025/03/13
2020
得物 Android Crash 治理实践
Linux QQ能打语音视频了!一文详解背后技术实现!
6 月 6 日,QQ For Linux 3.2.9 正式支持了音视频通话功能,这是 QQ Linux 版本的又一个里程碑事件。 2024 年,QQ 音视频正式推出 NTRTC,全平台(iOS/Android/MacOS/Windows/Linux)的支持是 NTRTC 的重要特性之一,本次 Linux 平台的适配也是这次升级过程中重要的一环。 本文作者详细记录了 QQ 音视频通话在 Linux 平台适配开发过程中的技术实现方案与一些细节,以帮助大家理解在 Linux 平台实现音视频通话能力的从 0 到 1 的过程。也欢迎大家下载最新版 Linux QQ 试用体验:im.qq.com/linuxqq
腾讯云开发者
2024/06/18
1.1K0
Linux QQ能打语音视频了!一文详解背后技术实现!
我用 Rust 改写了自己的C++项目:这两个语言都很折磨人!
作者 | Strager 译者 | 马可薇 策划 | 褚杏娟 C++ 漫长的构建时间可谓臭名昭著,编程圈的“我的代码在编译”只是个段子,但 C++ 让这个段子长盛不衰。 谷歌 Chromium 规模的项目在新硬件上的构建时间长达一小时,而在老硬件上的构建时间更是达到了六个小时。虽然也有海量的调整方案能加速构建速度,还有不少削减构建内容但极易出错的捷径供人选择,再加上数千美元的云计算能力,Chromium 的构建时间仍是接近十分钟。这点我完全无法接受,人们每天都是怎么干活的啊? 有人说 Rus
深度学习与Python
2023/03/29
1.6K0
我用 Rust 改写了自己的C++项目:这两个语言都很折磨人!
IM跨平台技术学习(十二):万字长文详解QQ Linux端实时音视频背后的跨平台实践
2024年6月6日,QQ For Linux 3.2.9 正式支持了音视频通话功能,这是 QQ Linux 版本的又一个里程碑事件。 2024 年,QQ 音视频正式推出 NTRTC,全平台(iOS/Android/MacOS/Windows/Linux)的支持是 NTRTC 的重要特性之一,本次 Linux 平台的适配也是这次升级过程中重要的一环。
JackJiang
2024/07/04
3910
IM跨平台技术学习(十二):万字长文详解QQ Linux端实时音视频背后的跨平台实践
手写系列-这一次,彻底搞懂 Promise
想要实现 Promise,必须先了解 Promise 是什么,以及 Promise 有哪些功能。
游魂
2023/10/17
3130
手写系列-这一次,彻底搞懂 Promise
推荐阅读
相关推荐
怎样让 C++ 中 throw exception 产生的 coredump 带上栈
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档