[转帖]踩内存问题分析工具

内存,问题,分析,工具 · 浏览次数 : 0

小编点评

**踩内存问题分析工具** **简介** 踩内存问题是进程崩溃时,无法生成coredump分析文件的问题。为了分析踩内存问题,可以使用一些工具来收集有关内存访问的信息,并通过分析这些信息来诊断问题。 **工具** 1. **gdb watch**:使用 gdb 命令监控程序变量的内存访问,并通过 watch 命令查看变量的值。 2. **asan**:使用 asan 工具对程序进行内存安全检查,可以检测踩内存问题。 3. **perf**:使用 perf 工具设置和读取内存的硬件中断,并可以通过分析中断信息来诊断问题。 4. **bcc**:使用 bcc 工具进行内存访问控制,可以限制访问某些内存区域。 5. **gdb hardware breakpoint**:使用 gdb 工具设置和访问内存的硬件中断,可以进行更精细的内存访问分析。 **使用说明** **gdb watch** 1. 运行程序并设置要监控的变量。 2. 使用 watch 命令监控变量的值变化。 3. 按回车键查看变量的值。 **asan** 1. 编译代码带有asan 指令。 2. 使用 asan 工具运行程序。 3. 检查asan报告中出现的踩内存错误。 **perf** 1. 运行程序并设置要读取内存的硬件中断。 2. 使用 perf 工具分析中断信息。 3. 按回车键查看中断信息。 **bcc** 1. 编译代码使用 bcc 指令对内存进行访问控制。 2. 使用 bcc 工具运行程序。 3. 检查 bcc报告中出现的踩内存错误。 **gdb hardware breakpoint** 1. 使用 gdb 工具设置和访问内存的硬件中断。 2. 在代码中设置硬件中断。 3. 使用 gdb 工具进行内存访问分析。 **注意事项** * 使用这些工具时,需要了解相关技术和命令。 * 某些工具可能需要特定版本或平台的支持。 * 踩内存问题可能很复杂,需要使用多种工具才能完全分析。

正文

踩内存问题,大家都知道,是一个比较难分析的问题。

踩内存问题被发现,通常是程序崩溃的时候,能够生成coredump分析,知道是哪个内存被踩了,但通常是很难分析出是哪段代码出现了踩内存的问题。

本文会介绍几种分析踩内存问题的工具,有些工具是最近发现的,我还没有大量使用过,所以只是个简单的介绍,各位看官自行判断是否实用。

文章写的比较匆忙,内容可能会不太完整,请各位见谅。

gdb watch

发现踩内存问题后,我们可以通过gdb来起出现问题的应用程序,然后对出现问题的变量进行watch,每次这个变量被读取/修改时,程序都会暂停,我们就可以看一下是不是正常的修改。

这个网上资料比较多,就不详细介绍了。

这种方法的缺点: 每次修改都会停下来,如果这个变量经常被修改,那么基本是无法调试的。不知道能否通过gdb脚本来解决这个问题。
优点:很灵活,可以设置对很多变量的watch,当然设多了会占用比较多的cpu;暂停下来以后,可以看的信息很多

mprotect

mprotect可以修改内存的权限,可以将需要保护的内存设置为只读,然后每次访问这块内存,进程就会接收到一个异常信号(应该是SIGSEGV),然后可以对这个信号注册回调函数,进行你需要的处理,例如打印调用栈。

当然正常的访问是不应该进行处理的,所以在正常的访问前,先执行mprotect将内存改为可读写,访问结束后,再改为只读。

mprotect还有一个问题,它只能对一整个page进行设置,并不能指定到一个字节,所以回调里面还得判断访问的是否你需要监视的内存,如果不是,还得进行比较复杂的处理:1. 将这个page设置为可读写,否则这个修改就无法完成了,会一直触发SIGSEGV信号。2. 修改完成之后,还得重新设置为只读,这时候的设置比较麻烦了,应该已经回归到正常运行状态了。有一种处理方法,可以先在触发异常的代码的下一行将代码修改为INT3指令(类似gdb断点的原理),那么就会触发中断,在中断中再进行设置,设置完再将INT3修改回原来的代码。

还是比较麻烦的,不是很推荐使用。

asan

asan本身自带踩内存的检测,只要编译时带上asan,就能够进行一些踩内存的检测了。

使用asan进行检测会有一些踩内存问题无法检测到,主要是踩的内存不在asan加的保护内存中,而是踩的正常内存,此时就检测不出来。

如果出现这种问题,还可以采用asan提供的ASAN_POISON_MEMORY_REGION宏,对指定的内存进行保护
参考:https://github.com/google/sanitizers/wiki/AddressSanitizerManualPoisoning

同样的,使用poison时,在正常的访问前,需要先解除保护,也就是unpoison,访问完成后,再进行poison。

这样就要求对所有会访问监视内存的代码前后进行修改,否则正常访问也会报错了。

perf(hardware breakpoint)

gdb的watch,在数量比较少的时候,应该也是使用的hardware breakpoint。perf提供了可以手动设置hardware breakpoint的方法,针对指定的内存设置hardware breakpoint之后,对这个内存的读写就会触发中断,然后由指定的处理函数进行处理,如果不指定,则是默认输出到trace。

这个正好试用了一下,记录一下使用示例:

使用perf,在内存0x5594191c6018上设置了hardware breakpoint,采集每次对该内存的访问情况:

root/$ sudo perf record -e mem:0x5594191c6018 -p $(pgrep bcc_test)
^C[ perf record: Woken up 55 times to write data ]
[ perf record: Captured and wrote 14.168 MB perf.data (450225 samples) ]

    perf script查看结果:

    root/$ sudo perf script
            bcc_test 12823 5633590.352853:          1 mem:0x5594191c6018:      5594191c31c1 _plus0+0x18 (/home/xuhaitao/test/bcc/build/bcc_test)
            bcc_test 12823 5633590.352856:          1 mem:0x5594191c6018:      5594191c31cb _plus0+0x22 (/home/xuhaitao/test/bcc/build/bcc_test)
            bcc_test 12823 5633590.352858:          1 mem:0x5594191c6018:      5594191c31c1 _plus0+0x18 (/home/xuhaitao/test/bcc/build/bcc_test)
            bcc_test 12823 5633590.352859:          1 mem:0x5594191c6018:      5594191c31cb _plus0+0x22 (/home/xuhaitao/test/bcc/build/bcc_test)
            bcc_test 12823 5633590.352860:          1 mem:0x5594191c6018:      5594191c31c1 _plus0+0x18 (/home/xuhaitao/test/bcc/build/bcc_test)
            bcc_test 12823 5633590.352861:          1 mem:0x5594191c6018:      5594191c31cb _plus0+0x22 (/home/xuhaitao/test/bcc/build/bcc_test)
            ......
    

      这样就能看到对内存0x5594191c6018进行访问和修改的位置了(_plus0+0x18和_plus0+0x22,也就是_plus0函数中的某个位置)。
      这个使用是很灵活的,可以打印调用栈,还可以搭配ebpf进行使用,进行一些统计分析、数据过滤。
      bcc也有人做过针对hardware breakpoint的开发,但没有入库,见:https://github.com/iovisor/bcc/pull/2456 希望以后能有成熟的bcc工具吧。

      这种方法也有一些缺点:1. 你需要知道内存地址,在进程中是容易获取到的,但通过终端命令的方法设置的话,获取内存地址可能会有一些困难。 2. 可以设置的hardware point数量有限,一般x86是支持4个

      除了终端命令的方式,也可以在代码中设置hardware point,参考系统提供的api:register_wide_hw_breakpoint

      与[转帖]踩内存问题分析工具相似的内容:

      [转帖]踩内存问题分析工具

      序 踩内存问题,大家都知道,是一个比较难分析的问题。 踩内存问题被发现,通常是程序崩溃的时候,能够生成coredump分析,知道是哪个内存被踩了,但通常是很难分析出是哪段代码出现了踩内存的问题。 本文会介绍几种分析踩内存问题的工具,有些工具是最近发现的,我还没有大量使用过,所以只是个简单的介绍,各位

      [转帖]记一次使用nacos2踩到的坑

      https://cloud.tencent.com/developer/article/2077110?areaSource=104001.26&traceId=7WZNP412yK3vh7ebw4th0 前言 本文素材来源朋友学习nacos2.1.1踩到的坑。直接上正菜 坑点一:出现端口被占用 因

      [转帖]MySQL Online DDL 原理和踩坑

      https://juejin.cn/post/6854573213167386637 MySQL Online DDL 原理和踩坑 MySQL 的 DDL(Data Definition Language) 包括增减字段、增减索引等操作。在 MySQL 5.6 之前,MySQL 的 DDL 操作会按

      [转帖]8 年 Redis 运维经验,我踩了哪些坑

      https://cloud.tencent.com/developer/article/1986942 Redis 目前绝对算是当前市场的宠儿,大到 BAT,小到初创公司都在使用。一说到 Redis,我们就会想到它的高性能、数据结构丰富、API 功能强大、高可用性以及架构可伸缩等特点。正是这些特点,

      [转帖]Redis Scan 原理解析与踩坑

      https://www.lixueduan.com/posts/redis/redis-scan/ 主要分析了 Redis Scan 命令基本使用和具体实现,包括 Count 参数与 Scan 总耗时的关系,以及核心的逆二进制迭代算法分析。 1. 概述 由于 Redis 是单线程在处理用户的命令,而

      [转帖]知道 Redis RDB 这些细节,可以少踩很多坑

      https://cloud.tencent.com/developer/article/2183079 在使用 Redis 的过程中,你是否遇到过下面这些问题: 开启 RDB 落盘,业务频繁出现请求超时。 除了 save 和 bgsave 命令,还有哪些操作会触发 RDB 落盘? 执行了 flush

      [转帖]Redis Scan 原理解析与踩坑

      https://www.cnblogs.com/jelly12345/p/16424080.html 1. 概述由于 Redis 是单线程在处理用户的命令,而 Keys 命令会一次性遍历所有 Key,于是在 命令执行过程中,无法执行其他命令。这就导致如果 Redis 中的 key 比较多,那么 Ke

      [转帖] 时区的坑,别再踩了!

      https://www.cnblogs.com/codelogs/p/16027236.html 原创:打码日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处。 简介# 最近在使用date命令时,发现表示东8区(中国时区)要使用GMT-8,但在Java中却需要使用GMT+8,如下:

      [转帖]k8s部署有状态应用redis-cluster集群踩坑总结

      https://segmentfault.com/a/1190000039196137 redis-cluster集群的部署网上一堆,用k8s部署也不在少数,但都是抄来抄去,问题不少,实际操作分享出来的还是太少。 1、redis启动配置文件,使用CofigMap来管理比较方便,redis-confi

      [转帖]Codis作者黄东旭:细说分布式Redis架构设计和那些踩过的坑

      https://dbaplus.cn/news-141-270-1.html Codis是一个分布式Redis解决方案,与官方的纯P2P模式不同,Codis采用的是Proxy-based的方案。今天我们介绍一下Codis以及下一个大版本RebornDB的设计,同时会介绍Codis在实际应用场景中的一