当GDB遇到STL

news2024/11/26 18:54:22

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.coloradmin.cn/o/1097194.html

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

相关文章

前端技术-并发请求

并发请求 代码解释 定义了一个函数 concurRequest&#xff0c;用于并发请求多个 URL 并返回它们的响应结果。 function concurRequest(urls, maxNum) {return new Promise((resolve, reject) > {if (urls.length 0) {resolve([]);return;}const results [];let index …

水果店在微信小程序中可以实现什么功能

一、开发背景 随着移动支付的普及和消费者需求的不断变化&#xff0c;越来越多的水果店开始关注线上销售和数字化运营。微信小程序作为一种轻量级应用&#xff0c;无需下载安装&#xff0c;即可实现与客户的无缝衔接。因此&#xff0c;开发一款针对水果店的微信小程序&#xff…

限制LitstBox控件显示指定行数的最新数据(1/3)

工作表Sheet1中的数据表共有3列&#xff0c;行数不确定&#xff0c;现需要将数据加载到用户窗体的ListBox控件中&#xff0c;设置控件的相关属性属性如下所示。 控件属性属性值ColumnCount3ColumnHeadsTrueRowSourceSheet1!A2:C15 窗体显示效果如下图所示&#xff0c;这里有一…

项目中 .env.development 与 .env.production 的区别

文章目录 一、项目中使用此两个文件的意义二、使用方式 一、项目中使用此两个文件的意义 我们在开发项目时&#xff0c;经常会有开发环境与生产环境&#xff0c;分别会对应不同的请求地址与各种不同的变量&#xff0c;这个时候我们就可以使用 process.env 去抓取这两个文件写的…

以漫画形式解说面向对象:把复杂的概念用简单有趣的画面呈现,启发你的思维

面向对象是什么 面向对象&#xff08;Object Oriented&#xff0c;OO&#xff09;的思想是软件开发中极其重要的概念和应用&#xff0c;它早已超越了程序设计和软件开发的范畴&#xff0c;延伸至数据库系统、交互式界面、应用结构、应用平台、分布式系统、网络管理结构、CAD技…

2023_Spark_实验十九:SparkStreaming入门案例

SparkStreaming入门案例 一、准备工作 二、任务分析 三、官网案例 四、开发NetWordCount 一、准备工作 实验环境&#xff1a;netcat 安装nc&#xff1a;yum install -y nc 二、任务分析 将nc作为服务器端&#xff0c;用户产生数据&#xff1b;启动sparkstreaming案例中的客户端…

BOSHIDA DC电源模块关于电容器的电解液位置

BOSHIDA DC电源模块关于电容器的电解液位置 DC电源模块中的电容器扮演着一个非常重要的角色&#xff0c;它们能够对电路提供稳定的电源电压&#xff0c;同时也可以作为电路中的滤波器&#xff0c;去除电路中的噪声和纹波。在DC电源模块中使用的电容器通常是电解型电容器&#…

unity(WebGL) 截图拼接并保存本地,下载PDF

截图参考&#xff1a;Unity3D 局部截图、全屏截图、带UI截图三种方法_unity 截图_野区捕龙为宠的博客-CSDN博客 文档下载&#xff1a; Unity WebGL 生成doc保存到本地电脑_unity webgl 保存文件_野区捕龙为宠的博客-CSDN博客 中文输入&#xff1a;Unity WebGL中文输入 支持输…

2023_Spark_实验十八:安装FinalShell

下载安装包 链接&#xff1a;https://pan.baidu.com/s/14cOJDcezzuwUYowPsOA-sg?pwd6htc 提取码&#xff1a;6htc 下载文件名称&#xff1a;FinalShell.zip 二、安装 三、启动FinalShell 四、连接远程 linux 服务器 先确保linux系统已经开启&#xff0c;不然连接不上 左边…

Linux离线安装Apache HTTP

准备工作 下载apr、apr-util、pcre、httpd包 apr、apr-util下载, 如下图: pcre下载,如下图: httpd下载 ,如下图: 开始安装 1. 安装编译apr [rootlocalhost ~]# cd /usr/local [rootlocalhost local]# tar -zxvf apr-1.7.4.tar.gz -C ./ [rootlocalhost local]# cd apr…

apple pencil买不买?ipad第三方电容笔推荐

相信很多学生党的学习都离不开iPad&#xff0c;然而电容笔&#xff0c;自然也是是必不可少的。至于真的Apple Pencil&#xff0c;那就更贵了&#xff0c;一支就要一千多块钱&#xff0c;普通人可买不起。国内的电容笔已经做得很好了&#xff0c;虽然不像苹果原装电容笔那样&…

186_Power BI Desktop 支持计算组编辑

186_Power BI Desktop 支持计算组编辑 一、背景 今天是2023年10月16日&#xff0c;基本上是 Power BI 每月更新的时间点了。打开看到 Power BI 果然已经更新到了2023年10月版本&#xff1a;2.122.746.0 (23.10) (x64) 这里提一下&#xff0c;我使用的是商店版的 Power BI De…

多线程中ThreadPoolExecutor.map()中传递多个参数

with concurrent.futures.ThreadPoolExecutor(max_threads) as executor:results executor.map(get_captcha_image, ip_addrs, [img_url] * len(ip_addrs)) #要传入多个参数时&#xff0c;每个参数都得是固定相同长度的可迭代对象# 收集结果for result in results:print(resul…

便利店小程序可以做哪些营销活动呢

在当今这个数字化时代&#xff0c;微信小程序已经成为了人们日常生活的一部分。对于便利店来说&#xff0c;拥有一个优秀的小程序不仅可以提高销售&#xff0c;还可以扩大品牌影响力&#xff0c;增加客户粘性。本文将探讨便利店小程序可以做什么样的营销活动&#xff0c;如何利…

智慧饭堂报餐系统源码 智慧食堂源码

智慧饭堂报餐系统源码 智慧食堂源码 技术栈 1、前端技术栈&#xff1a;ES6、vue、vuex、vue-router、vue-cli、axios、element-ui 2、后端技术栈&#xff1a;SpringBoot、MyBatis、Spring Security、Jwt 介绍 一款java开发的智慧饭堂报餐系统&#xff0c;支持连接人脸识别…

分享一下微信报名系统怎么做

微信报名系统是一种基于微信公众号或小程序的开发和应用&#xff0c;可实现用户通过微信进行在线报名、支付等操作的系统。本文将介绍微信报名系统的基本概念、制作流程、功能特点、使用流程和推广策略&#xff0c;帮助读者了解如何制作一个高效的微信报名系统。 一、微信报名系…

从零开始学习调用百度地图网页API:三、鼠标点击绘图功能

目录 代码功能问题注意addEventListenerplot_line 代码 <!DOCTYPE html> <html> <head><meta http-equiv"Content-Type" content"text/html; charsetutf-8" /><meta name"viewport" content"initial-scale1.0,…

WordPress 常规设置页面调用媒体中心上传图片插入URL(新版可用)

首先&#xff0c;我们需要在主题或插件文件夹中创建一个 JavaScript 文件&#xff08;如&#xff1a;media-uploader.js&#xff09;&#xff0c;该文件中包含如下代码。 /*** 媒体中心上传 js **/ jQuery(document).ready(function($){var mediaUploader;$(#upload_image_but…

AUTOSAR介绍

AUTOSAR产生背景 车辆功能的创新导致车辆E/E架构日益复杂。与此同时&#xff0c;开发要求通常自相矛盾&#xff1a;例如要求驾驶域辅助系统支持关键性驾驶操控&#xff0c;提高燃油经济性同时符合环境标准。信息娱乐和通信系统与实时车辆环境和在线服务的不断深入整合带来了更…

MASA MAUI 预览Office文件

文章目录 背景介绍1、新建MAUI Blazor项目2、创建OfficeViewer.razor组件3、使用安卓模拟器运行4、兼容iOS 总结 背景 接到一个在Maui中预览Office文件的需求&#xff0c;包含excel、word、PDF三种常见的文件&#xff0c;经过技术选型&#xff0c;最后选择了微软原生支持的off…