编程(一)C++内存泄露排查方法

背景描述

最近工作的内容是搭建推荐系统的debug平台,即将一次推荐请求过程中比较关键的推荐信息都以可视化的形式展现出来。举个例子,一个推荐系统处理推荐请求大致分为如下步骤(有点老老生常谈):

  1. 涉及到很多路召回(recaller),每路召回都会产出很多个候选资源(candidates);
  2. 这些候选资源会经过若干个过滤器(filter),将那些近乎无效的资源(重复、年代太久远)过滤掉;
  3. 粗略排序+精细排序(ranker),得到最终展现在用户面前的若干资源。

这只是最简单的过程,因为上述过程中的每个环节都有可能存在a/b test环节,因而你并不知道某一个资源从产生到展示在用户面前经历了哪些步骤,如果哪天某个老大报了一个case,说我一个年过半百的成功人士为什么要给我推送海绵宝宝?然后我们这群小弟就必须从上倒下捋一遍整个推荐过程,拉线上日志,费心费力地找了半天,才发现有一路召回可能存在问题,之后再上线修复这个case,这样排查case的方式费心费力。

从上面的背景可以看出搭建推荐系统debug平台的重要性,因而这个任务就落在了我这个新人头上。经过将近一个月的组内成员各方同步+编写代码之后,终于可以提测。测试环节QA提出我的代码有内存泄露的情况,1分钟服务器的内存增长1个G,我知道我这次的项目中会频繁操作内存,因为我要把整个推荐链路的信息都保存下来,但一分钟增长1个G,确实有点恐怖,确实有点吓人。

查阅资料

valgrind

QA大佬那边有一个排查内存泄露的工具,但是最近不能用,因为整个大组的C++的gcc是8.2版本的,公司内部的valgrind只支持gcc4.8.2,因而多番尝试之后放弃。

这里顺便附上valgrind的使用说明,希望能够对大家有所帮助。

asan

接下来是asan,这个工具在公司内部用的比较多,而且是整个大组一个架构大佬推荐的,操作比较简单,而且运行速度也比valgrind快,跑起来发现有个地方内存泄露,但是和我的代码无关,经过多番周折之后发现这段代码只是new和free没有匹配,写这段代码的大佬告诉我new和free虽然不匹配,但是后面代码"隐式调用"了free,因而依然没问题。跳过了new和free的不匹配选项,跑了一会发现根本没有内存泄露异常的报警,依然费解…

这里还是顺便附上asan的使用说明,希望能够帮到大家。

排查方法

无奈之下,我只能自己手动排查错误了,思考了很久,总结了一套方法:

  1. 首先要排查的是线上Base版本代码是否有问题,有的人可能会觉得好奇,为什么线上Base版本会出现问题,这是我的老大传授给我的,要对一切事情报以怀疑的态度,没有人规定线上版本不会出现问题,所有的错误如果都能在测试环节发现,就不会有所谓的线上事故了,跑了一遍,发现线上Base版本的代码在压测过程中内存涨到一定程度之后就稳定不变了;
  2. 将自己所有的代码都注释掉,然后逐个添加自己代码的核心功能,压测时看下内存变化,经过差不多一天的尝试之后,当添加记录资源信息功能时内存增长过快,问题找到,这里分享下我在排查过程中脑图的记录

经过排查代码和多方查证,发现protobuf会占用机器很多内存,特别是使用mutable和Clear的时候一定要小心,因为mutable操作不当会多申请内存,Clear过的数据结构并没有释放,而且重复使用,因而想出来的方案是降低使用protobuf的频次,这样能够最大化地降低内存增长的风险,如下是我查阅protobuf对内存增长相关的文档,希望能帮助到大家:

  1. Protobuf使用不当导致的程序内存上涨问题
  2. Protobuf中ShutdownProtobufLibrary函数的使用

总结

  1. 云端的内存泄露或者内存增长过快的问题一版不好排查,因为涉及到的模块很多,所以遇到这种问题时必须要冷静下来,在没有外界工具的前提下一定要冷静地思考到底哪里出现问题。
  2. 个人代码相关问题的解决只能靠自己,因为别人的工作都很忙,没有人能够平心静气地帮你捋一遍你的代码逻辑以及这个过程中出现的代码漏洞,这个责任只能你一个人扛。
  3. 抱着怀疑一切的态度工作,不放过任何一个可能出错的细节。
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值