定位多线程内存越界问题实践总结现象复现问题.PDFVIP

定位多线程内存越界问题实践总结现象复现问题.PDF

  1. 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  4. 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  5. 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  6. 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  7. 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
定位多线程内存越界问题实践总结现象复现问题

定位多线程内存越界问题实践总结 2013/2/4 杨志丰 yangzhifeng83@ 关键字 多线程,内存越界,valgrind ,electric-fence ,mprotect,libsigsegv,glibc 最近定位了在一个多线程服务器程序(OceanBase MergeServer)中,一个线程非法篡改 另一个线程的内存而导致程序 core 掉的问题。定位这个问题花了整整一周的时间,期间历 经曲折,尝试了各种内存调试的办法。往往感觉就要柳暗花明了,却发现又进入了另一个死 胡同。最后,使用强大的 mprotect+backtrace+libsigsegv 等工具成功定位了问题。整个定位 过程遇到的问题和解决办法对于多线程内存越界问题都很典型,简单总结一下和大家分享。 只对终极组合秘技感兴趣的同学,请直接阅读最后一节,其他的章节写到这里是为了科普。 现象 core 是在系统集成测试过程中发现的。服务器程序MergeServer 有一个50 个工作线程 组成的线程池,当使用8 个线程的测试程序通过MergeServer 读取数据时,后者偶尔会core 掉。用gdb 查看core 文件,发现core 的原因是一个指针的地址非法,当进程访问指针指向 的地址时引起了段错误(segment fault )。见下图。 发生越界的指针 ptr_位于一个叫做 cname_ 的对象中,而这个对象是一个动态数组 field_columns_ 的第10 个元素的成员。如下图。 复现问题 之后,花了2 天的时间,终于找到了重现问题的方法。重现多次,可以观察到如下一些 现象: 1. 随着客户端并发数的加大(从8 个线程到16 个线程),出core 的概率加大; 2. 减少服务器端线程池中的线程数(从50 个到2 个),就不能复现core 了。 3. 被篡改的那个指针,总是有一半(高4 字节)被改为了0 ,而另一半看起来似乎是 正确的。 4. 请看前一节,重现多次,每次出core,都是因为field_columns_这个动态数组的第 10 个元素data_[9]的cname_成员的ptr_成员被篡改。这是一个不好解释的奇怪现 象。 5. 在代码中插入检查点,从 field_columns_ 中内容最初产生到读取导致越界的这段代 码序列中“埋点”,既使用二分查找法定位篡改cname_ 的代码位置。结果发现,程 序有时core 到检查点前,有时又core 到检查点后。 综合以上现象,初步判断这是一个多线程程序中内存越界的问题。 使用glibc 的MALLOC_CHECK_ 因为是一个内存问题,考虑使用一些内存调试工具来定位问题。因为OB 内部对于内存 块有自己的缓存,需要去除它的影响。修改 OB 内存分配器,让它每次都直接调用 c 库的 malloc 和free 等,不做缓存。然后,可以使用glibc 内置的内存块完整性检查功能。 使用这一特性,程序无需重新编译,只需要在运行的时候设置环境变量MALLOC_CHECK_ (注意结尾的下划线)。每当在程序运行过程free 内存给glibc 时,glibc 会检查其隐藏的元 数据的完整性,如果发现错误就会立即abort 。 用类似下面的命令行启动server 程序: export MALLOC_CHECK_=2 bin/mergeserver -z 45447 -r 83:45401 -p45441 使用MALLOC_CHECK_以后,程序core 到了不同的位置,是在调用free 时,glibc 检查内 存块前面的校验头错误而abort 掉了。如下图。 但这个core 能带给我们想信息也很少。我们只是找到了另外一种稍高效地重现问题的 方法而已。或许最初看到的core 的现象是延后显现而已,其实“更早”的时刻内存就被破 坏掉了。 valgrind glibc 提供的MALLOC_CHECK_功能太简单了,有没有更高级点的工具不光能够报告错误, 还能分析出问题原因来?我们自然想到了大名鼎鼎的valgrind 。

文档评论(0)

laolao123 + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档