1 内存泄露分析
在堆上分配的内存,没有及时释放掉,以便后面其它地方可以重用。在C/C++中,内存管理器不会帮你自动回收不再使用的内存。如果你忘了释放不再使用的内存,这些内存就不能被重用,就造成了所谓的内存泄露。
一两处内存泄露通常不至于让程序崩溃,也不会出现逻辑上的错误,当然了,量变会产生质变,一旦内存泄露过多以致于耗尽内存,后续内存分配将会失败,程序可能因此而崩溃。
内存访问越界,使用的内存超出了向系统申请了一块内存,覆盖该空间之后的一段存储区域,导致系统异常。
常见原因:
1.写越界,又叫缓冲区溢出,所写入的数据对别人来说是随机的,它也会产生不可预料的后果。
向10个字节的数组写入了20个字节;内存操作越界。
如char szText[10];memset(szText,0,30); //访问越界了,10字节空间,修改了30字节
2.读越界,即读了不属于自己的数据,如果所读的内存地址是无效的,程度立刻就崩溃了。如果所读内存地址是有效的,在读的时候不会出问题,但由于读到的数据是随机的,它会产生不可预料的后果。
内存越界访问造成的后果非常严重,是程序稳定性的致命威胁之一。更麻烦的是,它造成的后果是随机的,表现出来的症状和时机也是随机的,让BUG的现象和本质看似没有什么联系,这给BUG的定位带来极大的困难。
一些工具可以够帮助检查内存越界访问的问题,但也不能太依赖于工具。内存越界访问通常是动态出现的,即依赖于测试数据,在极端的情况下才会出现,除非精心设计测试数据,工具也无能为力。工具本身也有一些限制,甚至在一些大型项目中,工具变得完全不可用。比较保险的方法还是在编程是就小心,特别是对于外部传入的参数要仔细检查。
2 内存泄漏检测工具Valgrind的安装与使用
Valgrind是一个Linux平台的内存调试工具。它允许你在Valgrind自己的环境中运行你的程序,监视内存使用,例如:调用malloc和free(或者是C++中的new和delete)。如果使用未初始化的内存,数组访问越界或者忘记释放指针,Valgrind就能够检测出来。使用valgrind之前 ,当然是要拥有它了。
2.1 Valgrind的安装
Valgrind地址:https://valgrind.org/downloads/current.html
Valgrind可以在线安装,当然也可以使用源码安装。
如果你是Ubuntu系统,直接使用以下命令安装Valgrind即可。
$sudo snap install valgrind # version 3.21.0, or
$sudo apt install valgrind # version 1:3.15.0-1ubuntu9.1
Valgrind最新的版本是V3.21.0,直接下载valgrind-3.21.0.tar.bz2压缩包进行源码安装。
$tar -xvf valgrind-3.21.0.tar.bz2
$./configure --prefix=/usr/local/valgrind
$make
$sudo make install
使用以上命令,valgrind就安装在你的系统里面了,不管使用在线安装还是源码安装只要能安装上Valgrind就行。
2.2 valgrind的使用
valgrind能够发现使用非法的堆内存。下面就使用valgrind来查看内存泄漏。
#include <stdlib.h>void fun(void)
{int* x = malloc(10 * sizeof(int));x[10] = 0; // problem 1: heap block overrun
} // problem 2: memory leak -- x not freedint main(void)
{fun();return 0;
}
$ gcc main.c -g -o main
值得注意的是,变异需要加-g参数。
$ valgrind --tool=memcheck --leak-check=full ./main
==4813== Memcheck, a memory error detector
==4813== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==4813== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==4813== Command: ./main
==4813==
==4813== Invalid write of size 4
==4813== at 0x10916B: fun (main.c:6)
==4813== by 0x109180: main (main.c:11)
==4813== Address 0x4a50068 is 0 bytes after a block of size 40 alloc'd
==4813== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==4813== by 0x10915E: fun (main.c:5)
==4813== by 0x109180: main (main.c:11)
==4813==
==4813==
==4813== HEAP SUMMARY:
==4813== in use at exit: 40 bytes in 1 blocks
==4813== total heap usage: 1 allocs, 0 frees, 40 bytes allocated
==4813==
==4813== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1
==4813== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==4813== by 0x10915E: fun (main.c:5)
==4813== by 0x109180: main (main.c:11)
==4813==
==4813== LEAK SUMMARY:
==4813== definitely lost: 40 bytes in 1 blocks
==4813== indirectly lost: 0 bytes in 0 blocks
==4813== possibly lost: 0 bytes in 0 blocks
==4813== still reachable: 0 bytes in 0 blocks
==4813== suppressed: 0 bytes in 0 blocks
==4813==
==4813== For lists of detected and suppressed errors, rerun with: -s
==4813== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
可以看到有对泄漏信息进行检测,有两个错误,并且指出产生泄漏的代码及代码行数。