当GDB遇到STL

STL是标准模板库(Standard Template Library)的简称,是C++的三大件之一。

c745a134f4d86fab9065807de1144738.png

Alex是STL的核心设计者。他于1950年出生在莫斯科,后来到美国发展,曾经在Adobe、A9.com等公司工作。在Adobe工作时,他和保罗•麦克琼斯是同事和好朋友,他们曾合作出版了《Elements of Programming》一书。

我在写作《软件简史》时,结识了保罗,多次和他邮件来往和视频交流。在保罗为《软件简史》的序言里,特别提到,他曾和Alex一起邀请Fortran之父约翰•巴克斯到Adobe做主旨演讲。

9cdc3f9742bab972be702f3ccb140d22.png

STL的第一大特色当然就是模板。模板增加了STL库的通用性,也让STL具有了如下两个特色:

- 源代码难读,难理解

- 不好调试

对于不好调试,又可以分解为如下两点:

- 模板展开后的类型名和函数名往往很长,冗长晦涩,令人生畏

- 观察STL对象时,经常看到一些难以理解的设计细节,看不到用户关心的属性。

针对这样的问题,我特别在GDB系列讲座的序言一讲,用一个案例分享了用GDB调试STL有关问题时的挑战和化解方法。

46a3f83c0b3a490f10ecca1638f34b10.png

我先尝试在x86虚拟机里打开core文件,

7aac56cb3dadab54c69ea1b0df63e91f.png

GDB给出了四个警告,两对问号,连寄存器这样的基本信息都没有。

使用readelf观察,原因是core文件是在arm64上系统产生的。

0b8b869fa264efb51937be702428fc03.png

于是换gdb-multiarch来打开,情况大为好转,不仅可以看到崩溃点,还可以看到比较完美的调用栈。

dc30fbd8cc7055829b78aeee056c5fd2.png

崩溃发生在dog_t类的构造函数中:

85def6801293a9d25c157ccc9731698f.png

构造函数异常简单,看起来不应该有错误:

dog_t(int age, const char* name){age_ = age;name_ = name;}

从反汇编来看,是访问对象指针时出错了。

1817429e2ca381ff04a1d581756dd69e.png

对象指针哪里来的呢?来自父函数。

顺着调用栈一级级看父函数,这时就感觉到前面说的问题了,很长的类名,很长的参数名。

只有栈帧5简短,ge_work,看起来是个纯粹的c函数。

使用frame命令切换ge_work,再l,可以看到它的源代码:

void ge_work(void* ptr_vdogs, int no)
{int i = 0;vector<dog_t>* vdogs = (vector<dog_t>*)ptr_vdogs;cout << "thread "<< no << " starts working" << endl;do {vdogs->push_back(dog_t(no*(i++), "little dog"));} while(1);
}

看起来这个函数是在使用stl的vector容器,在向容器里面存入dog_t对象。

于是便想知道,崩溃时容器里已经有了多少对象,使用p命令观察,看到的都是“噪声”:

a582a501ac4215f80c8df84ca705ac50.png

接下来,我换用幽兰代码本来分析同样的core文件。

5440ca18f2944edec953c8f53bc8906c.png

打开core文件后,gdb便自动下载调试符号,因为幽兰上已经预先配置好了基于debuginfod的符号服务器。

接下来使用同样步骤切到栈帧5,用p命令观察容器,这次就看到了我们想看到的信息:

b5a7056e0f85b26f5ca642cb2b66c26e.png

与上次看到的信息对比,这次看到的太美好了,不仅包含清楚的元素列表,而且还包含向量的两个关键属性:length和capacity。

让我们惊讶的是,length值为2056,capacity的值为2048。

这是不对的啊,length代表的是实际元素个数,capacity代表的是容器的容纳能力,前者应该小于后者才对。

但是现在前者大于后者了,显然是有问题的。

怎么会出现这样的情况呢?

使用info threads列出进程里的所有线程:

5480383d2d1b78d78be2b5052d9ba186.png

然后使用thread apply all命令观察每个线程的调用栈。

浏览gdb显示的结果,可以看到4号线程也在操作stl的vector对象。

6ad8674c4af69018f843d055d54650bc.png

切换到这个线程,观察它操作的vector对象,将其与1号线程对比,竟然是同一个vector.

d90a2fafe4620a7389b598b6da54e588.png

这显然是代码错误了。标准stl的容器是不支持并发的,也就是多线程使用时要程序员自己加锁进行保护。这就是这个案例的bug。

那么为什么在幽兰上很顺利观察到stl对象属性,快速找到bug了呢?主要原因有如下两个。

首先,幽兰上的gdb版本很高,是非常新的13.1。而不顺利的虚拟机里面,gdb的版本是7。

geduer@ulan:~/gelabs/gestl$ gdb --version

GNU gdb (Ubuntu 13.1-2ubuntu2) 13.1

其实,正是从gdb 7.0开始,gdb引入了pretty-printers功能,使用python脚本来解析stl对象,以优雅的格式显示用户希望看到的属性。

d78338e7cd4c6ae471183de34a28483d.png

但是根据我的实际测试,这个功能在一些版本的gdb 7上工作的并不好。所以还是使用高一些的版本更稳妥。

另一个原因是幽兰上自动启用了符号服务器,可以通过互联网从服务器上下载libc等库模块调试符号。有了这些符号后,才可以顺利观察多个线程的调用栈。

比如,在没有使用符号服务器时,线程列表里的信息只有1号线程比较完整,其它线程都缺少当前函数信息。

e96a0603894b6f047895add80215c062.png

有了符号后,信息便完整了。

78098bfcd5d5baf058cfcaa32a6ed47b.png

GDB是软件工程师需要修炼的一门硬功夫。在接下来的大约2个月时间里,我会每周六直播一讲,以实战方式讲解gdb的用法。

想和我们一起学习的同行可以在微信中搜索盛格塾小程序,然后搜GDB(注意大写),便可以找到这门课程。

68596f649c4d7e715c10965851349178.png

(写文章很辛苦,恳请各位读者点击“在看”,也欢迎转发)

*************************************************

正心诚意,格物致知,以人文情怀审视软件,以软件技术改变人生

扫描下方二维码或者在微信中搜索“盛格塾”小程序,可以文章和有声读物

1e235a31587e49148400724b4d95e1b7.png

也欢迎关注格友公众号

e736d970a293139497a2e8681f91bb07.jpeg

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

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

相关文章

字符串思维题练习 DAY6 (CF 245H , CF 559B , CF 1731C , CF1109B)

字符串思维题练习 DAY6 (CF 245H , CF 559B , CF 1731C &#xff0c; CF1109B) CF 245 H. Queries for Number of Palindromes&#xff08;字符串 dp&#xff09; Problem - H - Codeforces 大意&#xff1a;给出一个字符串S (|S| ≤ 5000) , 给出 Q 次询问 &#xff0c; 每…

参数解析(牛客)

目录 一、题目 二、代码 一、题目 二、代码 #include <iostream> #include <vector> using namespace std;int main() {string s;getline(cin, s);int i 0;vector<string>ret;while (i < s.size()){if (s[i] )//遇到空格直接跳过{i;}else if (s[i] …

Fbank及MFCC学习

Fbank&#xff1a;FilterBank&#xff1a;人耳对声音频谱的响应是非线性的&#xff0c;Fbank就是一种前端处理算法&#xff0c;以类似于人耳的方式对音频进行处理&#xff0c;可以提高语音识别的性能。获得语音信号的fbank特征的一般步骤是&#xff1a;预加重、分帧、加窗、短时…

day14I102.二叉树的层序遍历

1、102.二叉树的层序遍历 题目链接&#xff1a;https://leetcode.cn/problems/binary-tree-level-order-traversal/ 文章链接&#xff1a;https://programmercarl.com/0102.%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E5%B1%82%E5%BA%8F%E9%81%8D%E5%8E%86.html#%E7%AE%97%E6%B3%95…

详细教程:Postman 怎么调试 WebSocket

WebSocket 是一个支持双向通信的网络协议&#xff0c;它在实时性和效率方面具有很大的优势。Postman 是一个流行的 API 开发工具&#xff0c;它提供了许多功能来测试和调试 RESTful API 接口&#xff0c;最新的版本也支持 WebSocket 接口的调试。想要学习更多关于 Postman 的知…

PDE数值解中,为什么要引入弱解(weak solution)的概念?

See https://www.zhihu.com/question/24243246?utm_sourceqq&utm_mediumsocial&utm_oi1315073218793488384

[Python]黑色背景白色块滑动视频

黑色背景白色块滑动视频&#xff0c;单帧效果如下&#xff1a; 配置参数 1920 1080 400 400 300 60 1920x1080.avi import numpy as np import cv2 as cv import os import syswidth 1920 height 1080 rect_szx 400 rect_szy 300 sz_y_init 400 fps 24width int(sys.a…

十进制小数 与 二进制小数 互转

1、十进制小数 转 二进制小数 公式 小数 * 2得到n1, 将n1的整数作为二进制数第一位&#xff1b;n1的小数 * 2得到n2, 将n2的整数作为二进制数第二位&#xff1b;n2的小数 * 2得到n3, 将n3的整数作为二进制数第三位&#xff1b;… 重复以上步骤&#xff0c;直到小数部分为0或者…

竞赛选题 深度学习+opencv+python实现车道线检测 - 自动驾驶

文章目录 0 前言1 课题背景2 实现效果3 卷积神经网络3.1卷积层3.2 池化层3.3 激活函数&#xff1a;3.4 全连接层3.5 使用tensorflow中keras模块实现卷积神经网络 4 YOLOV56 数据集处理7 模型训练8 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &am…

在服务器上解压.7z文件

1. 更新apt sudo apt-get update2. 安装p7zip sudo apt-get install p7zip-full3. 解压.7z文件 7za x WN18RR.7z

java合成多个pdf为一个pdf

pom文件 <dependency><groupId>com.lowagie</groupId><artifactId>itext</artifactId><version>2.1.7</version></dependency>主文件 import com.lowagie.text.Document; import com.lowagie.text.pdf.PdfCopy; import com.lo…

求三维坐标绕坐标轴旋转后的坐标值

目的 旋转矩阵 应用 沿单个坐标轴旋转 沿多个坐标系旋转 目的 由于其他文章原理介绍比较详细&#xff0c;但应用方面较少。本文直接介绍旋转矩阵的应用&#xff0c;条件为坐标系不变&#xff0c;求旋转后的三维坐标。本文方法较傻瓜式&#xff0c;需要自己进行测试以确认是…

HUAWEI(26)——防火墙双机热备

一、拓扑 二、需求 PC2 ping PC1 FW1与FW2双机热备,FW1为active,FW2为Standby,抢占延时1s VRRP 三、配置 1.IP地址,防火墙接口加入区域 防火墙用户名:admin 防火墙旧密码:Admin@123 防火墙新密码:admin@123 [FW1]interface GigabitEthernet 1/0/0 [FW1-GigabitEthe…

振弦传感器和无线振弦采集仪在隧道安全监测的解决方案

振弦传感器和无线振弦采集仪在隧道安全监测的解决方案 隧道作为交通工程的重要组成部分&#xff0c;具有极高的安全风险&#xff0c;因此隧道安全监测是必不可少的。振弦传感器和无线振弦采集仪作为隧道安全监测的两种重要设备&#xff0c;能够有效地监测隧道的振动情况&#…

elasticsearch(ES)分布式搜索引擎03——(RestClient查询文档,ES旅游案例实战)

目录 3.RestClient查询文档3.1.快速入门3.1.1.发起查询请求3.1.2.解析响应3.1.3.完整代码3.1.4.小结 3.2.match查询3.3.精确查询3.4.布尔查询3.5.排序、分页3.6.高亮3.6.1.高亮请求构建3.6.2.高亮结果解析 4.旅游案例4.1.酒店搜索和分页4.1.1.需求分析4.1.2.定义实体类4.1.3.定…

解决uniapp里scroll-view横向滚动的问题

一、前言 本以为是一件很简单的事&#xff0c;结果浪费了整整一个上午&#xff0c;并且问题并没有全部解决....后来没办法&#xff0c;用了touchmove模拟的滑动&#xff0c;如果有好的解决方法麻烦告诉我...非常感谢~ 一、问题 其实我想要实现的功能很简单&#xff0c;就是一…

微服务、SOA 和 API 之间的区别

在软件开发中&#xff0c;组织的投资方式发生了重大转变&#xff0c;部署了面向架构的方法。这一切都始于 SOA&#xff0c;然后转变为我们称之为微服务的东西。添加到其中的是另一个概念&#xff0c;指定为 API。 在过去的几年里&#xff0c;SOA 和微服务仍然是讨论的话题。随…

【红外双目有监督】CATS系列数据集探索加载器

论文&#xff1a; CATS: A Color and Thermal Stereo Benchmark https://www. flir.com/oem/adas/adas-dataset-form/.Flir thermal dataset 数据集规格 内容 总共 26,442 个 完全注释的帧&#xff0c;以及 15 个不同对象类别的520,000 个 边界框注释。 图片 9,711 张热图像和…

Lazysysadmin靶机

信息收集 主机发现 nmap -sn 192.168.88.0/24 //-sn&#xff1a;制作主机发现&#xff0c;不做端口扫描&#xff1b;扫描结果包含本机IP 端口扫描 nmap --min-rate 10000 -p- 192.168.88.136 扫描端口详细信息 端口扫描发现&#xff0c;该主机的22、80、139、445、3306、…

软件开源快速开发框架:降本增效,助力流程化办公!

随着时代的进步和社会的发展&#xff0c;应用软件开源快速开发框架的优势特点&#xff0c;可以让不少客户朋友顺利实现流程化办公&#xff0c;朝着数字化方向迈进。流辰信息是专业研发低代码技术平台的服务商&#xff0c;一直在低代码平台领域深耕细作&#xff0c;努力钻研&…