作者:糖果

【问题】
寻找内存泄露,有时是一件困难的事情。代码的内存申请和释放动作不配对,或是在并发环境下,时序变换的异常,都会引起的内存泄露,即使从core dump回溯调用栈,也未必能找到快速内存的泄露点。

某些嵌入式系统,对制造方式有特殊的限制,不允许使用智能指针或是STL库。编码的错误引起的内存泄露机率等问题,可以提前通过第三方软件静态检查,输出错误报告,从而找到问题的代码。

对稍微复杂的嵌入式系统而言,在UI层,中间件层,驱动层,都可能发生泄露。特别是在并发环境下的时序异常,引起的泄露就比较难找,可以用GDB attach 断点,或是输出系统Log,进行问题的切分。

如何解决?
Linux也提供了一种,不需要debug或是改代码的情况下,进行内从泄露检查的机制。在linux的proc目录下,有与系统进程同名的文件目录,进入目录后可以查看此进程的各种相关信息。

例如,要查看系统中一个叫做candy的进程的内存使用情况,就可以按如下步骤进行。

1)取得“candy”进程的PID号。

ps -elf | grep candy

2)查看进程使用内存的信息,假设candy的PID号是1688。

cat /proc/1688/status

在屏幕上输出的项目中有一项“VmData: xxxK”这一项就是进程使用堆的情况。

3)打印时间戳和内存占用情况(时间间隔3秒)。

clear;date;cat /proc/1688/status | grep VmData;sleep 3;echo "######";date;echo "######";cat /proc/1688/status | grep VmData

如果想查看系统UI进程是否有异常,就可以在UI进程启动后,通过运行类似于上面这种脚本,查看系统内存变化,进入某页面,然后不触发UI界面上的任何操作,分别在观察开始结束两个时间点,观察系统占用情况,如果伴随时间的变化,VmData的值变化明显,越来越大,基本可以切分出,这个页面内存泄露的可能性很大,然后在进行系统log代码级别的问题切分。

有些时候,我们希望有一个声音提醒,可以在脚本结尾,加一句gst-launch播放音乐的命令,在等待一定时间后,通过播放音乐,进行提醒,另外也可以把结果直接通过管道输入到文件里。

如何查看进程使用了那些文件句柄?

有些功能需要频繁的打开关闭文件,如果程序执行的某个时间点,忽略了文件关闭的动作,特别是写实时log到文件里的功能,某一处没关闭该关的文件,造成log内容逻辑错乱。
{问题:在复杂的时序条件下,很难判断是哪个文件没关上。}

ls -anl /proc/1688/fd

通过这行命令就可以看到,当前的进程都使用了那些文件,其中也包括socket句柄。

如何有兴趣,可以看看nginx进程的这个数据。

注释:个人劳动成果,使用请注明,本文作者及出处链接,谢谢合作!

测试