一种内存泄露检查和定位的方法

简介:

一个系统后台服务进程,可能包括多个线程,在生成环境下要求系统程序能够稳定长时间稳定运行而不宕机。其中一个基本的前提就是需要保证系统程序不存在内存泄露。那么,该如何判读系统程序是否存在内存泄露呢?如果存在,又该如何检测呢?


0.判读系统程序是否存在内存泄露


对于频繁快速申请内存的应用,可以允许下面的命令:

top -p `pidof YourProgrogram`

如果看到系统内存使用率一直上身,没有下降,就说明很可能存在内存泄露。


对于申请、使用内存比较缓慢的应用程序,可以通过下面的命令,观测一天乃至一周内内存使用率的变化:

for ((i=0;i<100000;i++)); do pidstat -p `pidof YourProgram` -tr | tee -a thread_mem_static.txt; sleep 10; done

如果上面显示的RSS的内存随着时间推移不断增加,且不符合程序预期,那么很可能存在内存泄露。

wKiom1kldwCwT594AACBIKNXC_I693.png


1.定位内存泄露的线程或代码位置


检查主进程的每个线程的page fault的频率,虽然page fault频率高的不一定有内存泄露,但有内存泄露的线程的page fault的频率一定很高。而体现每个线程Page fault频率的指标就是上图中每个线程的minflt/s值,如果它的值一直偏高,就说明该线程反复申请内存或者不停在栈上使用buffer,此时就需要利用gdb打印出每个线程信息,可以参考下面的gdb命令:

gdb -q --batch --ex "thread apply all bt" -p `pidof tmem`


根据上面对应的线程号找到相应函数,然后进行跟踪,可以参考下面的示例:

wKiom1kldxazCMXjAACNIqwhe9E836.png


上图中显示线程14178 (mem_funcs)线程频繁使用新的内存,查看代码,果然存在内存泄露:

wKioL1kldybSHUPvAAA3z8L6iSI743.png


需要强调的是,只有RSS不一直增加,哪怕minflt/s一直增加,也表明没有内存泄露,比如下面的测试程序,频繁使用栈上空间:


void internal_mem_funcs(void)

{

long int test[MAX_BUF_LEN] = {0,};

//long int * test = (long int *)malloc(MAX_BUF_LEN * sizeof(long int));

int i = 0;


for (i = 0; i < MAX_BUF_LEN; i++) {

test[i] = random();

}


return;

}


它的pidstat统计图如下:

wKiom1kldzmyFIPKAAB-fMtRoVk000.png


2.常见的内存泄露方式


笔者最近分析了一个系统服务进程内存泄露的问题,下面总结了一些代码中很容易出现内存泄露的地方:

  • 函数正常成功执行的时候有释放内存,但在执行异常退出的时候,没有释放所有先前申请的内存;

对类似strdup()/strndup()/g_strdup()的函数的返回值,使用完之后,没有释放内存的意识;

  • 不同模块或者层次的代码相互调用的时候,没有统一约定好是调用者申请内存、释放内存还是被调用者申请、释放内存,抑或是调用者申请/释放内存,被调用者释放/申请内存,导致后面遗忘释放内存或者重复释放内存;

  • Java/c++中对异常处理的流程中,遗忘没有释放内存;

  • 使用了一些不太熟悉的第三方库代码,对类似句柄、描述符、对象相关的API了解不够深入,导致没有也不知道该如何释放内存。

















本文转自存储之厨51CTO博客,原文链接:http://blog.51cto.com/xiamachao/1929118  ,如需转载请自行联系原作者



相关文章
|
2月前
|
监控 Linux
如何检查 Linux 内存使用量是否耗尽?这 5 个命令堪称绝了!
本文介绍了在Linux系统中检查内存使用情况的5个常用命令:`free`、`top`、`vmstat`、`pidstat` 和 `/proc/meminfo` 文件,帮助用户准确监控内存状态,确保系统稳定运行。
506 6
|
2月前
|
监控 JavaScript 算法
如何使用内存监控工具来定位和解决Node.js应用中的性能问题?
总之,利用内存监控工具结合代码分析和业务理解,能够逐步定位和解决 Node.js 应用中的性能问题,提高应用的运行效率和稳定性。需要耐心和细致地进行排查和优化,不断提升应用的性能表现。
188 77
|
2月前
|
监控 JavaScript Java
Node.js中内存泄漏的检测方法
检测内存泄漏需要综合运用多种方法,并结合实际的应用场景和代码特点进行分析。及时发现和解决内存泄漏问题,可以提高应用的稳定性和性能,避免潜在的风险和故障。同时,不断学习和掌握内存管理的知识,也是有效预防内存泄漏的重要途径。
138 52
|
2月前
|
传感器 人工智能 物联网
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发,以及面临的挑战和未来趋势,旨在帮助读者深入了解并掌握这些关键技术。
51 6
|
2月前
|
缓存 Linux
如何检查 Linux 内存使用量是否耗尽?
何检查 Linux 内存使用量是否耗尽?
|
3月前
|
机器学习/深度学习 算法 物联网
大模型进阶微调篇(一):以定制化3B模型为例,各种微调方法对比-选LoRA还是PPO,所需显存内存资源为多少?
本文介绍了两种大模型微调方法——LoRA(低秩适应)和PPO(近端策略优化)。LoRA通过引入低秩矩阵微调部分权重,适合资源受限环境,具有资源节省和训练速度快的优势,适用于监督学习和简单交互场景。PPO基于策略优化,适合需要用户交互反馈的场景,能够适应复杂反馈并动态调整策略,适用于强化学习和复杂用户交互。文章还对比了两者的资源消耗和适用数据规模,帮助读者根据具体需求选择最合适的微调策略。
673 5
|
3月前
|
缓存 监控 Java
在使用 Glide 加载 Gif 动画时避免内存泄漏的方法
【10月更文挑战第20天】在使用 Glide 加载 Gif 动画时,避免内存泄漏是非常重要的。通过及时取消加载请求、正确处理生命周期、使用弱引用、清理缓存和避免重复加载等方法,可以有效地避免内存泄漏问题。同时,定期进行监控和检测,确保应用的性能和稳定性。需要在实际开发中不断积累经验,根据具体情况灵活运用这些方法,以保障应用的良好运行。
|
3月前
|
存储 Java
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
这篇文章详细地介绍了Java对象的创建过程、内存布局、对象头的MarkWord、对象的定位方式以及对象的分配策略,并深入探讨了happens-before原则以确保多线程环境下的正确同步。
66 0
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
|
4月前
|
Java 测试技术 Android开发
Android性能测试——发现和定位内存泄露和卡顿
本文详细介绍了Android应用性能测试中的内存泄漏与卡顿问题及其解决方案。首先,文章描述了使用MAT工具定位内存泄漏的具体步骤,并通过实例展示了如何分析Histogram图表和Dominator Tree。接着,针对卡顿问题,文章探讨了其产生原因,并提供了多种测试方法,包括GPU呈现模式分析、FPS Meter软件测试、绘制圆点计数法及Android Studio自带的GPU监控功能。最后,文章给出了排查卡顿问题的四个方向,帮助开发者优化应用性能。
237 4
Android性能测试——发现和定位内存泄露和卡顿
|
5月前
|
缓存 Ubuntu Linux
在Linux中,如何检查系统的CPU和内存使用情况?
在Linux中,如何检查系统的CPU和内存使用情况?

热门文章

最新文章