Linux内存泄漏
0 什么是内存泄漏?
内存泄漏(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
1 常见的造成内存泄漏的原因
1.1 指针重新赋值
下面是一段示例代码:
char * p = (char *)malloc(10);
char * np = (char *)malloc(10);
其中,指针变量p和np分别被分配了10个字节的内存,它们各自的内存如图所示

如果程序执行如下赋值语句:
p=np;
这时候,指针变量p被np指针重新赋值,其结果是p以前所指向的内存位置变成了孤立的内存,如图所示。它无法释放,因为没有指向该位置的引用,从而导致 10 字节的内存泄漏。

因此,在对指针赋值前,一定确保内存位置不会变为孤立的。
1.2 错误的内存释放
假设有一个指针变量 p,它指向一个10字节的内存位置。该内存位置的第三个字节又指向某个动态分配的 10 字节的内存位置,如图所示。

如果程序执行如下语句:
free(p);
很显然,如果通过调用 free 来释放指针 p,则 np 指针也会因此而变得无效。np 以前所指向的内存位置也无法释放,因为已经没有指向该位置的指针。换句话说,np 所指向的内存位置变为孤立的,从而导致内存泄漏。
因此,每当释放结构化的元素,而该元素又包含指向动态分配的内存位置的指针时,应首先遍历子内存位置(如本示例中的 np),并从那里开始释放,然后再遍历回父节点,如下面的代码所示:
free(p->np);
free(p);
1.3 返回值的不正确处理
有时候,某些函数会返回对动态分配的内存的引用,如下面的示例代码所示:
char *f()
{
return (char *)malloc(10);
}
void f1()
{
f();
}
很明显,函数 f1 中对 f 函数的调用并未处理该内存位置的返回地址,其结果将导致 f 函数所分配的 10 个字节的块丢失,并导致内存泄漏。
1.4 内存malloc()分配后忘记使用free()进行释放
1.5 使用open()、fopen()后忘记使用close()、fclose()
2 内存泄漏的表现
2.1 应用程序崩溃
因为内存泄漏导致已运行的应用程序得不到所需的内存空间而出现崩溃。
2.2 内存占用量持续增长不减
内存泄漏会导致被泄露的内存在本次系统运行期间不能被使用,因此,随着时间的推移,内存占用量是持续增长的。
2.3 触发OOM,进程被kill
当系统无法为新进程分配内存时,可能会触发OOM,系统选择一些进程,然后kill他们。
3 如何定位内存泄漏
3.1 用户态内存泄漏
- 使用top指令查看系统中占用内存量较高的进程
top

观察以下参数:
VIRT 进程使用的虚拟内存
RES 进程使用的真实内存
SHR 共享内存
%MEM 内存占用率
M 按内存占用率(%MEM)排序

2. 找出内存占用量较高的进程后,记下该进程的PID,如上图的609。
3. 执行如下指令查看进程内存方面的详细信息。
watch -n 1 cat "/proc/"`ps -ef | grep PID | grep -v grep | awk 'NR==1 {print $2}'`"/status"

我们主要查看一下几个参数的值:
VmPeak:进程使用的虚拟内存的峰值
VmSize:进程当前使用的虚拟内存的大小
VmLck:已锁住的物理内存的大小(不能交换到磁盘)
VmHWM:进程使用的物理内存的峰值
VmRSS:进程当前使用的物理内存的大小
如果VmSize或VmRSS在一段时间内占用异常,可以考虑该进程是否存在内存泄漏。
4. 借助内存泄漏分析工具进行分析
推荐使用内存泄漏分析工具--valgrind
valgrind --tool=memcheck --leak-check=full xxx //xxx为该进程的二进制可执行文件的绝对路径
执行完毕后我们要观察的主要是如下图的信息:

Definitely lost:确认丢失,程序中存在内存泄漏,需要尽快修复。
Indirectly lost:间接丢失,常与definitely lost一起出现,只要修复definitely lost即可。
Possibly lost:可能丢失,大多数情况下应视为definitely lost,需要尽快修复。
Still reachable:可以访问的,这些内存没有丢失、没有释放。建议修复。
Suppressed:已解决的,可以无视此部分。
5. 假如有内存泄漏,则需要找出源码进行修复。
那如何快速定位是哪个位置出现了内存泄漏呢?
根据valgrind的打印信息快速定位。举例如下:

这个例子就说明了/root目录下的a.out程序存在4字节的内存泄漏,即test()函数里面的new操作存在泄漏,即new完没有对应的delete。(从下往上执行)
找到泄漏的原因,我们就可以在源码中找到对应的位置进行修复。
6. valgrind也不是万能的,存在如下缺点(包括但不限于):
1. valgrind会占用了更多的内存--会达到检测程序的两倍
2. valgrind不检查静态分配数组的使用情况
3. valgrind检测时新启动了一个进程,不能监测正在运行的进程
3.2 内核态内存泄漏
对于内核态内存泄漏的排查方法和工具,我不了解。如有好的参考资料可以评论区留言,谢谢各位dalao。
本文持续更新
Linux内存泄漏的更多相关文章
- Linux 内存泄漏 valgrind
Valgrind 是个开源的工具,功能很多.例如检查内存泄漏工具---memcheck. Valgrind 安装: 去官网下载: http://valgrind.org/downloads/curre ...
- Linux 内存泄漏检查工具 valgrind
抄自<从零开始的JSON库教程>,先mark一下,以后再慢慢研究. ======== 引用分割线 ======== 在 Linux.OS X 下,我们可以使用 valgrind 工具(用 ...
- Linux/Unix使用valgrind内存泄漏检测
c\c++程序设计.内存管理是一个比较头疼的问题.相信它会导致内存泄漏.除了外部养成良好的编程习惯(使用智能指针),使用该工具还可以帮助检测内存泄漏,valgrind这是Unix\Linux在一个很好 ...
- 如何在linux下检测内存泄漏
之前的文章应用 Valgrind 发现 Linux 程序的内存问题中介绍了利用Linux系统工具valgrind检测内存泄露的简单用法,本文实现了一个检测内存泄露的工具,包括了原理说明以及实现细节. ...
- 如何在linux下检测内存泄漏(转)
本文转自:http://www.ibm.com/developerworks/cn/linux/l-mleak/ 本文针对 linux 下的 C++ 程序的内存泄漏的检测方法及其实现进行探讨.其中包括 ...
- 【linux】linux下对java程序生成dump文件,并使用IBM Heap Analyzer进行分析,查找定位内存泄漏的问题代码
1.首先,java程序启动在linux,怎么生成dump文件? 1>第一步,首先你需要得到java程序的PID,最简单的方法使用如下命令 ps -ef|grep java 或者如果是docker ...
- Linux下内存泄漏工具【转】
转自:http://www.cnblogs.com/guochaoxxl/p/6970090.html 概述 内存泄漏(memory leak)指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况 ...
- 在 Linux 平台中调试 C/C++ 内存泄漏方法(转)
由于 C 和 C++ 程序中完全由程序员自主申请和释放内存,稍不注意,就会在系统中导入内存错误.同时,内存错误往往非常严重,一般会带来诸如系统崩溃,内存耗尽这样严重的后果.本文将从静态分析和动态检测两 ...
- Linux下内存泄漏工具
概述 内存泄漏(memory leak)指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况,在大型的.复杂的应用程序中,内存泄漏是常见的问题.当以前分配的一片内存不再需要使用或无法访问时,但是却 ...
随机推荐
- python日志装饰器实现
问题出自:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143184355 ...
- feiQ发送信息
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import j ...
- iOS应用跳转至app store 评分页
小功能之去AppStore评分 #pragma mark - 去AppStore评分 -(void)goToAppStore { NSString *str = [NSString stringWit ...
- 让我一时不知所措 Linux 常用命令 爱情三部曲 下部
Linux目录与文件管理 我试着把你忘记,可总在夜里想你~ 1.linux目录结构 2.查看及检索文件 3.压缩及解压缩文件 4.vi文本编辑器 1.Linux目录结构:树形目录结构根目录:所有分区, ...
- AI模型运维——GPU性能监控NVML和DCGM
最近一年负责运维的GPU主机越来越多,发现现有的监控项无法很好的了解GPU的性能和负载情况,研究了下官方文档,在此记录. 一.NVML和DCGM NVML:https://developer.nvid ...
- Oracle用户创建、删除和授权等方法总结
一.查看用户及权限 1.查询所有用户: 1.1.查看所有用户基本信息 select * from all_users; 1.2.查看所有用户相信信息 select * from dba_users; ...
- 手把手教你实现pynq-z2条形码识别
我是 雪天鱼,一名FPGA爱好者,研究方向是FPGA架构探索和SOC设计. 关注公众号,拉你进"IC设计交流群". 1.前言 单单实现一个二维码识别就花了将近一个星期,这篇文章我就 ...
- Solution -「SDOI 2018」「洛谷 P4606」战略游戏
\(\mathcal{Description}\) Link. 给定一个 \(n\) 个点 \(m\) 条边的无向连通图,\(q\) 次询问,每次给出一个点集 \(s\),求至少在原图中删去多 ...
- Solution -「多校联训」博弈
\(\mathcal{Description}\) Link. A B 两人在树上博弈,初始时有一枚棋子在结点 \(1\).由 A 先操作,两人轮流移动沿树上路径棋子,且满足本次移动的树上距离 ...
- vscode使用vue代码模板
1.vscode中打开:文件>首选项>用户片段>vue.json 2.复制下面代码并保存. 点击查看代码 { "Print to console": { &quo ...