背景
之前判断判断程序内存有没有泄漏,是使用top命令观察RES的值是否在不断增长。这两天在排查内存泄漏问题时在网上看到两篇文章,按照这两篇文章的意思,判断一个程序的内存有没有泄漏是通过VIRT
来判断的。本文档意在搞清楚判断一个程序是否出现内存泄漏的指标。
上文提到的文章网址
https://blog.csdn.net/leacock1991/article/details/111086130
https://blog.csdn.net/jersonborn521/article/details/123043740
前置知识
VIRT
1.进程“需要的”虚拟内存大小,包括进程使用的库、代码、数据,以及malloc、new分配的堆空间和分配的栈空间等;
2、假如进程新申请10MB的内存,但实际只使用了1MB,那么它会增长10MB,而不是实际的1MB使用量。
3、VIRT=SWAP+RES
RES
1、进程当前使用的内存大小,包括使用中的malloc、new分配的堆空间和分配的栈空间,但不包括swap out量;
2、包含其他进程的共享;
3、如果申请10MB的内存,实际使用1MB,它只增长1MB;
4、RES=CODE+DATA
SHR
1、除了自身进程的共享内存,也包括其他进程的共享内存;
2、虽然进程只使用了几个共享库的函数,但它包含了整个共享库的大小;
3、计算某个进程所占的物理内存大小公式:RES – SHR;
4、swap out后,它将会降下来。
内存泄漏
内存发生泄漏是因为我们的程序通过大量的malloc或者new操作来申请内存的后,没有及时或者根本没有释放内存导致的,
推断
根据以上知识可推断出
- 1.RES是进程实际使用的内存大小,RES<=进程开辟空间的大小,即RES<=VIRT。有可能进程开辟10MB的空间,但实际只使用了1MB,那么RES的值为1MB,运行一段时间之后进程需要空间增长到2MB,那么RES的值为2MB,注意这时并没有调用mallo或者new来开辟空间;
- 2.进程在运行过程中没有开辟空间,那么VIRT不会增大;
- 3.进程在运行过程中开辟了空间,那么VIRT就会增大;
- 4.进程在运行过程中没有开辟空间,但随着程序的运行需要使用的空间增大了,导致RES增大,当RES增大到一定值时会导致程序崩溃;
实验 – 推断证明
实验1
代码如下:
int main()
{
int len = 1024 * 1024 * 100;
int i = 0;
char *p[10] = {NULL};
sleep(5);
printf("malloc mem\n");
for(int i = 0 ; i < 10; i++) //每过10s,开辟100MB的使用空间,共开1GB空间
{
printf("malloc-%d\n", i);
p[i] = (char*)malloc(len);
sleep(10);
}
printf("use mem\n");
for(int i = 0 ; i < 10; i++) //每过10s,增加100MB的使用空间
{
printf("use-%d\n",i);
memset(p[i], 1, len);
sleep(10);
}
printf("free mem\n");
for(int i = 0 ; i < 10; i++) //每过10s,释放100MB的使用空间
{
printf("free-%d\n",i);
free(p[i]);
sleep(10);
}
return 0;
}
内存使用情况如下图:
实验代码分为3个阶段
-
开辟内存环节–malloc mem
代码运行开始阶段,开辟了1GB的内存,此时使用top命令并没有显示出程序使用内存的情况,可能是因为没有占用实际内存。
-
使用内存环节–use mem
进入use mem之后,每过10s,增加100MB的使用空间,此时top命令显示出程序的内存使用情况,可以看到VIRT没有增加,随着使用空间的增大,RES出现了增大。
-
释放内存环节–free mem
释放内存,VIRT和RES都在减小
实验2
代码
int main()
{
int len = 1024 * 1024 * 1000;
int i = 0;
char *p[10] = {NULL};
sleep(5);
printf("malloc mem\n");
for(int i = 0 ; i < 10; i++) //开10GB空间
{
printf("malloc-%d\n", i);
p[i] = (char*)malloc(len);
sleep(10);
}
printf("use mem\n");
for(int i = 0 ; i < 10; i++) //每过10s,增加1GB的使用空间
{
printf("use-%d\n",i);
memset(p[i], 1, len);
sleep(10);
}
printf("free mem\n");
for(int i = 0 ; i < 10; i++) //每过10s,释放1GB的使用空间
{
printf("free-%d\n",i);
free(p[i]);
sleep(10);
}
return 0;
}
内存使用情况如下图:
实验代码分为3个阶段
-
开辟内存环节–malloc mem
代码运行开始阶段,开辟了10GB的内存,此时使用top命令并没有显示出程序使用内存的情况,可能是因为没有占用实际内存。
-
使用内存环节–use mem
进入use mem之后,每过10s,增加1GB的使用空间,此时top命令显示出程序的内存使用情况,可以看到VIRT没有增加,随着使用空间的增大,RES出现了增大, 当RES增大到7.8g之后被系统kill。
-
释放内存环节–free mem