linux 分析内存泄漏,Linux内存泄漏查询方法proc/status解释

如果笼统的来看,大概就是两个指标,系统的内存使用率和进程使用的内存。但是现实世界的事情往往没有那么简单,稍微细一点来看其实有很多的科目。本文不是一个全面的关于内存使用的探讨,甚至也不是一个详细的Linux下面进程内存使用情况的分析,尽管这里的实践是基于此的。

这里想做的是稍微细节一点的来看Linux下一个进程的内存使用情况,包括栈和堆。

首先我们从一个简单的C程序开始。且慢,先说一下我试验的环境。

platform:  CentOS release 5.6 (Final)  Linux localhost.localdomain 2.6.18-238.19.1.el5xen #1 SMP Fri Jul 15 08:57:45 EDT 2011 i686 i686 i386 GNU/Linux

gcc version 4.1.2 20080704 (Red Hat 4.1.2-50)

[root@localhost test]# cat simple_hello.c

#include

int main()

{

int i,m = 1024, n = 0,

x;

int a[m];

printf("assign %d values to a[%d]...\n", n, m);

for (i = 0; i < n; i++)

{

a[i] = 100;

}

printf("value assigned.\n");

scanf("%d", &x);  /* to hold program.. */

return 0;

}

真是一个很简单的程序,只比hello world复杂一点点。创建一个静态的数组,长度通过m来控制,然后选择性的给部分或者全部的元素赋值,通过n来控制。好吧,这个一个简单的程序能看出什么呢?那我们一起来看看。

在Linux下面,查看一个进程的内存使用我们可以下面的命令来实现,只需把其中的[pid]换成进程实际的pid。

# cat /proc/[pid]/status

为了方便,我们把查找pid和看内存整合成一条命令,后面这将是我们唯一的测试工具。

cat /proc/`ps -ef|grep hello | grep -v grep | awk '{print $2}'`/status | grep -E 'VmSize|VmRSS|VmData|VmStk|VmExe|VmLib'

在这里我们关注VmSize|VmRSS|VmData|VmStk|VmExe|VmLib 这个6个指标,下面有一些简单的解释。

VmSize(KB) :虚拟内存大小。整个进程使用虚拟内存大小,是VmLib, VmExe, VmData, 和 VmStk的总和。

VmRSS(KB):虚拟内存驻留集合大小。这是驻留在物理内存的一部分。它没有交换到硬盘。它包括代码,数据和栈。

VmData(KB):程序数据段的大小(所占虚拟内存的大小),堆使用的虚拟内存。

VmStk(KB):任务在用户态的栈的大小,栈使用的虚拟内存

VmExe(KB):程序所拥有的可执行虚拟内存的大小,代码段,不包括任务使用的库

VmLib(KB) :被映像到任务的虚拟内存空间的库的大小

Ok, 测试开始了。

首先,我们固定m的值为409600,相当于400K,因为数组的元素是int型,在我的环境里面是4Byte,所以真个数组的大小为1600KB。

m固定化,我们不断调整n的大小,重写编译,执行,然后用上面的命令查看内存的使用情况,这样我们得到了下面这个表格。

61709981_1.gif

从这里我们可以得到几个信息:

1. 静态的数组使用的空间被分配到VmStk,也就是栈区。

2. 在数组没有初始化的时候并没有实际占用虚拟内存,看VmRss,但是整个虚拟内存的大小还是分配了,VmSize。

接下来我们做另一个测试,让n=m,调整m的大小,也就是说调整数组的大小,然后初始化所有的元素。

这样我们得到了下面的表。

61709981_2.gif

从这个表中,我们可以看出:

1. 栈的使用确实和数组的size相关,但是有个起始预分配的大小,应该是编译器的优化。

2. VmRSS和VmSize跟着一起在涨。

嗯,是跟着在涨,但是有个问题,栈的空间是有限的,通过这个程序或者你查看系统的设置你可以找到上限。在我的这台机器上上限是8MB,每个进程,所以这里如果m的值大于2048000,就会出segmentation

fault的错误。当然你也可以调整系统的设置,比如通过

# ulimit -s 10240

将上限调为10MB。但是这个终究不能调得很大,因为对系统会有影响。所以编程中太大的静态数组不是有个好主意。

栈的大小限制还是蛮严格的,好吧,那我们来看看程序可以使用的另一类存储空间,堆(heap)。关于堆和栈的区别可能是一个常被问道的问题,你在很多地方可以找到答案。

OK,我们继续我们的实验,考虑到现在很多系统的后台用C++来写,我们也把测试程序换成C++的。好吧,我承认其实没有太大的区别,只是申请内存的方式不太一样了。

[root@localhost test]# cat hello.cpp

#include

using namespace std;

int main()

{

cout<

intm = 409600, n = 409600;

int *p = new int[m];

for (int i = 0; i < n; i++)

{

p[i] = 100;

}

cout<

int x;

cin>>x;  //hold program

}

这个我们使用的是动态的数组,也就是说数组的内容空间是我们显式的通过new通过向系统申请的。测试工具还是上面的命令行。

延迟我们的风格,首先固定m的值,这里是409600,400K,然后调整n的值,看情况是怎样的。

61709981_3.gif

一些观察的结果:

1. VmData的大小约为1600KB,因为每个元素4Byte,系统还有一些别的使用。

2. n控制有多少数组的元素被初始化,这也影响了VmRSS的大小。

整个VmSize的大小并不受初始化范围的影响,这个结果和之前栈的实验中看到的现象很类似,只不过这里换成了VmData。

接下来我们让n=m,然后两个一起调整。

61709981_4.gif

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值