一.内存错误出现的场景

这几天在重构ATS插件代码的过程中遇到了烦人的内存泄露问题, 周五周六连续两天通过走查代码的方法,未能看出明显的导致内存错误的代码, 同时也觉得C和C++混合编程得到一个动态库, 在一个.cpp主文件中,即用new又用malloc来动态分配内存, 可能会导致内存错误.后来网上调研和查资料发现, new和malloc混用还是允许的,因为C++兼容C.虽然这种混用方式不提倡, 但绝对不会导致内存堆栈错乱的情况.

这里之所以采用C和C++混合编程,是因为业务需要. ATS插件目前设计为一个transform主框架, 外加若干子模块, 一个子模块一个动态库,后者可以根据不同业务需要进行扩展,而transform类型的插件框架一般不变, 它只完成通常的transform变换流程就可以了. 这个主框架是使用C++开发的, 它提供了业务实现接口, 供每个业务动态库实现.因为接口入参中用到了stl的map结构来在主框架和子模块之间传递参数,所以接口的实现必须是C++方式的. 但是我的一个业务插件原来是使用纯c编写的, 引用了几个第三方库,比如JSON, libz, pcre库等, 它们原来已经用C编写好了,并且经过测试发现是可靠的, 如果再换为C++实现一般不太现实, 也没有必要. 这样造成的局面就是, 目前只能C和C++进行混合编程, 对C提供的接口, 要在h文件中使用 extern "C"声明, 并将实现存放在对应的c文件中.(这里必须要分离成两个文件, 如果以前只有一个h文件就搞定的, 现在要分为h和c文件).在编译出一个so时, 同时要外链其他的第三方基础库时, Makefile的编写通常有些技巧的, 请参见我的博文

C和C++混合编程的Makefile的编写!

这种情况下, 对C那部分的调用,我采用malloc和free来分配和释放内存, 对上层接口那部分, 我在主cpp文件中使用new和delete来分配内存.这里明显使得内存的使用更加复杂化了,但是不管怎样,按理说这种做法还是行得通的.

但是在调试过程中,我却发现了一个内存越界的错误, 每次提示的错误都不一样, 但是显示出错的位置又没有明显的错误, 真是让人摸不到头脑, 搞不定了, 郁闷, 失败至极.....

二.内存错误出现的表象

两天的搜索无果, 让我只能寻求内存检测软件的帮助. 我以前用过tcmalloc, 就是google的gperftools里面的一个工具,它会将系统默认的内存分配释放函数替换为自己的函数再进行检测,但是在这里不方便施展, 因为这里new和malloc都用上了, 所以我决定使用valgrind来检测. 具体安装使用方法,请参见

在Ubuntu 14.04 64bit上安装Valgrind并检查内存泄露

下面是ATS插件运行中崩溃时valgrind检测的几个错误截图

该截图告诉我们, pool_alloc(在mem_manage.c第17行)调用malloc分配了1813字节内存, find_replace_html(位于main.cpp第484行)函数使用memcpy从1808处开始要复制8个字节, 而事实上只能复制4字节,这会内存越界,导致非法的8字节写入(越界写入).

该截图告诉我们,  pool_alloc(在mem_manage.c第17行)调用malloc分配了1813字节内存,pcre_exec(在 regex_lookup.h第45行)在1813字节后面越界读取了1个字节.

该截图告诉我们, 在分配的1813字节内部的1808字节处, 要非法读取8字节内存(越界读取)

三.内存错误的分析和确定

上面的截图分析, 很明确地传递出内存越界读取和越界写入的错误, 但是我查看内存分配的地方, 没有看到明显的错误.但是多次调试显示的内存错误大多显示到memset这样的地方, 将部分memset代码注释掉后, 程序能运行, 但是运行一段时间后,它还是会有段错误, 看来找到的位置不对, 而且上面截图显示的都是造成错误的表现, 不是真正造成内存出错的地方.最后经过认真理解valgrind的错误提示, 和仔细地分析代码, 终于定位到内存错误的真正地方不是malloc长度那里, 而是memset那里, 初始化内存的那个指针只能是一个void*或char*, 不能是一个结构体, 这就是内存错误的真正地方.

参见下面的截图, 有内存错误的源码截图

改正内存错误的源码截图

改正后, 重新编译调试, 一切正常, 运行很长时间, 都没有再崩掉, 再次印证修改是正确的.而这个错误, 是一个大家看起来很可笑的问题, 所要大家编写代码时还是要提高修养和注意力,千万不要马虎写代码,否则会害死自己的.

四.回顾反思

bug不可怕, 犯错不可耻, 但是仔细分析导致bug的原因, 吸取教训并避免再犯才是最重要的. 另外一点是, 排错的锻炼和快速定位是一项职业素养, 越修bug越有收获越能提高, 经历越丰富自信心越强, 所以bug来了,我们还是得从容面对.

使用valgrind检测ATS插件中的内存泄露相关推荐

  1. ios代码中的内存泄露,内存检测工具leaks 检测不出来

    iphone开发过程中,代码中的内存泄露我们很容易用内存检测工具leaks 检测出来,并一一改之,但有些是因为ios 的缺陷和用法上的错误,leaks 检测工具并不能检测出来,你只会看到大量的内存被使 ...

  2. Android稳定性系列-01-使用 Address Sanitizer检测原生代码中的内存错误

    前言 想必大家曾经被各种Native Crash折磨过,本地测试没啥问题,一到线上或者自动化测试就出现各种SIGSEGV.SIGABRT.SIGILL.SIGBUS.SIGFPE异常,而且堆栈还是崩溃 ...

  3. Linux下几款C++程序中的内存泄露检查工具

    Linux下编写C或者C++程序,有很多工具,但是主要编译器仍然是gcc和g++.最近用到STL中的List编程,为了检测写的代码是否会发现内存泄露,了解了一下相关的知识. 所有使用动态内存分配(dy ...

  4. vs调试c语言检查内存泄露,VisualStudio中检查内存泄露方法

    项目工程中存在内存泄露,被折磨了一晚上,终于查了出来,因为之前没有相关的经验,还比较生疏,在此记录下来,方便以后查找. 对于malloc出的内存的检测方法 这篇文章中详细地记录了从检查到找到确定位置到 ...

  5. go技术日报(2021-10-20)——定位并修复 Go 中的内存泄露

    每日一谚:Go trusts the programmer to write down what is meant. go中文网每日资讯--2021-10-20 一.Go语言中文网 不要写破坏性的 G ...

  6. LeakCanary——消除Android中的内存泄露

    2019独角兽企业重金招聘Python工程师标准>>> ##LeakCanary ####简介 LeakCanary是Square公司最近公布的开源项目,旨在消除Android中的内 ...

  7. LeakCanary——直白的展现Android中的内存泄露

    之前碰到的OOM问题,终于很直白的呈现在我的眼前:我尝试了MAT,但是发现不怎么会用.直到今天终于发现了这个新工具: 当我们的App中存在内存泄露时会在通知栏弹出通知: 当点击该通知时,会跳转到具体的 ...

  8. Java中的内存泄露的几种可能

    转载自  Java中的内存泄露的几种可能 Java内存泄漏引起的原因: 内存泄漏是指无用对象(不再使用的对象)持续占有内存或无用对象的内存得不到及时释放,从而造成内存空间的浪费称为内存泄漏. 长生命周 ...

  9. 如何在iPhone应用中避免内存泄露

    本篇文章将介绍几个在iPhone APP中避免内存泄露的小技巧 关于所有权 所有权是iPhone内存管理的核心思想,对象的所有者负责在使用完对象后进行释放.一个对象可以有多个所有者,当它没有所有者时将 ...

最新文章

  1. 解决:AttributeError: ‘Graph‘ object has no attribute ‘number_of_selfloops‘
  2. GitHub上的这本开源算法书火爆了
  3. cart2pol函数
  4. 夜深人静,想规划一下短期
  5. ElementUI:文本框实现远程搜索的用法
  6. 软件工程基础知识--需求分析
  7. Redis的下载与安装——Windows版
  8. 2016年U盘启动盘制作工具哪个好用?看U盘启动盘排行榜!
  9. PX4模块设计之十二:High Resolution Timer设计
  10. 谈谈我对服务网格的理解
  11. 专业测试-自评抑郁量表SDS_悟sphenic_新浪博客
  12. 55句史上最伤人的语录集:看完一阵心酸啊
  13. Appium自动化测试元素定位方式
  14. 电脑的“应用与浏览器控制”出现黄色感叹号
  15. 考研英语不熟悉的词义(List16-List20)
  16. deepstream系列gst-shark工具分析插件效率
  17. MongoDB 3.2.7 for rhel6.4 副本集-分片集群部署
  18. Java数组,集合,列表的使用与区别
  19. 关于 web 性能的思考与分享[04]——页面 SEO 优化方案
  20. 南邮Android软件设计报告,南京邮电大学软件设计实验报告

热门文章

  1. 2022-2028年中国绝缘栅双极晶体管(IGBT)行业投资分析及前景预测报告
  2. Linux 终端推荐 Terminator
  3. 1.低权限的程序向高权限的程序发消息 2.慎用setcurrentdirectory
  4. 【原创】Cookie应用(二)
  5. linux安装vsftpt服务,centos安装vsftp服务.md
  6. 学校计算机机房好处,浅谈学校计算机机房维护
  7. oracle cdc 提交顺序,Oracle CDC部署流程
  8. 软件测试黑盒测试实验心得_软件测试的基础知识
  9. linux部分基础命令总结,Linux 基础命令总结3
  10. 该文件 linux命令,Linux网络系统,如果执行行命令#chmod 746 file.txt,那么该文件的权限是?...