Linux下检测程序内存泄漏

Linux下检测程序内存泄漏

工具:valgrind

Linux下载方式:yum install valgrind

内存泄漏:程序在heap上分配了内存却没有释放

写一个c语言内存泄漏程序:

#include <stdlib.h>
void f()
{
	int *t=malloc(sizeof(int)*10);
}
int main()
{
    int *array = malloc(10*sizeof(int));
    f();	
    return 0;
}	

很简单的一个程序,f()和main中都有malloc申请内存但是没有释放,故运行该程序会造成内存泄漏。

编译后生成a.out文件: gcc -g -o a.out test.c

运用valgrind检测内存泄漏:

 valgrind --tool=memcheck --leak-check=full  ./a.out

运行结果:

[root@jessy /]#  valgrind --tool=memcheck --leak-check=full  ./a.out
==14588== Memcheck, a memory error detector
==14588== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==14588== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==14588== Command: ./a.out
==14588== 
==14588== 
==14588== HEAP SUMMARY:
==14588==     in use at exit: 80 bytes in 2 blocks
==14588==   total heap usage: 2 allocs, 0 frees, 80 bytes allocated
==14588== 
==14588== 40 bytes in 1 blocks are definitely lost in loss record 1 of 2
==14588==    at 0x4C29F73: malloc (vg_replace_malloc.c:309)
==14588==    by 0x400556: main (test.c:8)
==14588== 
==14588== 40 bytes in 1 blocks are definitely lost in loss record 2 of 2
==14588==    at 0x4C29F73: malloc (vg_replace_malloc.c:309)
==14588==    by 0x40053E: f (test.c:4)
==14588==    by 0x400564: main (test.c:9)
==14588== 
==14588== LEAK SUMMARY:
==14588==    definitely lost: 80 bytes in 2 blocks
==14588==    indirectly lost: 0 bytes in 0 blocks
==14588==      possibly lost: 0 bytes in 0 blocks
==14588==    still reachable: 0 bytes in 0 blocks
==14588==         suppressed: 0 bytes in 0 blocks
==14588== 
==14588== For lists of detected and suppressed errors, rerun with: -s
==14588== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

可以看到,在head summary中,有该程序使用的总heap内存量,分配内存次数和释放内存次数,如果分配内存次数和释放内存次数不一致则说明有内存泄漏。

下面会有具体的分析:包括在main函数中和f函数中通过malloc申请了内存但是没有释放造成了多大的内存损失都标记有,–甚至行号都标记了,debug神器!

最下面有泄漏内存的总概况。

再来一个测试程序,测试一下重复free的情况:

#include <stdlib.h>
void f()
{
	int *t=malloc(sizeof(int));
	free(t);
	free(t);   //非法的free
}
int main()
{
    int *array = malloc(10*sizeof(int));
    f();	
    return 0;
}	

运行结果:

[root@jessy /]# gcc -g -o a.out test.c
[root@jessy /]#  valgrind --tool=memcheck --leak-check=full  ./a.out
==16670== Memcheck, a memory error detector
==16670== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==16670== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==16670== Command: ./a.out
==16670== 
==16670== Invalid free() / delete / delete[] / realloc()
==16670==    at 0x4C2B06D: free (vg_replace_malloc.c:540)
==16670==    by 0x4005AA: f (test.c:6)
==16670==    by 0x4005CC: main (test.c:12)
==16670==  Address 0x52050b0 is 0 bytes inside a block of size 4 free'd
==16670==    at 0x4C2B06D: free (vg_replace_malloc.c:540)
==16670==    by 0x40059E: f (test.c:5)
==16670==    by 0x4005CC: main (test.c:12)
==16670==  Block was alloc'd at
==16670==    at 0x4C29F73: malloc (vg_replace_malloc.c:309)
==16670==    by 0x40058E: f (test.c:4)
==16670==    by 0x4005CC: main (test.c:12)
==16670== 
==16670== 
==16670== HEAP SUMMARY:
==16670==     in use at exit: 40 bytes in 1 blocks
==16670==   total heap usage: 2 allocs, 2 frees, 44 bytes allocated
==16670== 
==16670== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1
==16670==    at 0x4C29F73: malloc (vg_replace_malloc.c:309)
==16670==    by 0x4005BE: main (test.c:11)
==16670== 
==16670== LEAK SUMMARY:
==16670==    definitely lost: 40 bytes in 1 blocks
==16670==    indirectly lost: 0 bytes in 0 blocks
==16670==      possibly lost: 0 bytes in 0 blocks
==16670==    still reachable: 0 bytes in 0 blocks
==16670==         suppressed: 0 bytes in 0 blocks
==16670== 
==16670== For lists of detected and suppressed errors, rerun with: -s
==16670== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

可以看到有一个非法的free命令,在第6行。可以看到main中函数是产生了内存泄漏,f 函数产生了非法的free。所以哪怕free和malloc数量相同也不能说明没问题呀。

最后再来一个测试程序,测试一下未初始化写内存的情况:

#include <stdlib.h>
void f()
{
	int *p; //未初始化
	p[0]=1;
	
}
int main()
{
    int *array = malloc(10*sizeof(int));
    f();	
    return 0;
}	

运行结果:

[root@jessy /]# vim test.c
[root@jessy /]# gcc -g -o a.out test.c
[root@jessy /]#  valgrind --tool=memcheck --leak-check=full  ./a.out
==17798== Memcheck, a memory error detector
==17798== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==17798== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==17798== Command: ./a.out
==17798== 
==17798== Use of uninitialised value of size 8
==17798==    at 0x400535: f (test.c:5)
==17798==    by 0x40055C: main (test.c:11)
==17798== 
==17798== Invalid write of size 4
==17798==    at 0x400535: f (test.c:5)
==17798==    by 0x40055C: main (test.c:11)
==17798==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==17798== 
==17798== 
==17798== Process terminating with default action of signal 11 (SIGSEGV)
==17798==  Access not within mapped region at address 0x0
==17798==    at 0x400535: f (test.c:5)
==17798==    by 0x40055C: main (test.c:11)
==17798==  If you believe this happened as a result of a stack
==17798==  overflow in your program's main thread (unlikely but
==17798==  possible), you can try to increase the size of the
==17798==  main thread stack using the --main-stacksize= flag.
==17798==  The main thread stack size used in this run was 8388608.
==17798== 
==17798== HEAP SUMMARY:
==17798==     in use at exit: 40 bytes in 1 blocks
==17798==   total heap usage: 1 allocs, 0 frees, 40 bytes allocated
==17798== 
==17798== LEAK SUMMARY:
==17798==    definitely lost: 0 bytes in 0 blocks
==17798==    indirectly lost: 0 bytes in 0 blocks
==17798==      possibly lost: 0 bytes in 0 blocks
==17798==    still reachable: 40 bytes in 1 blocks
==17798==         suppressed: 0 bytes in 0 blocks
==17798== Reachable blocks (those to which a pointer was found) are not shown.
==17798== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==17798== 
==17798== Use --track-origins=yes to see where uninitialised values come from
==17798== For lists of detected and suppressed errors, rerun with: -s
==17798== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Segmentation fault

这次内容有点多。逐一看看:首先就是访问了未初始化内存的内存(也标记了函数的名称和行号),访问未初始化内存导致了段错误。并且有内存泄漏。

猜你喜欢

转载自blog.csdn.net/dingdingdodo/article/details/107562656