linux
程序内存泄漏排查
一、前言
C/C++的内存操作一直是一种“诟病”,主要就是由于程序员调用API去操作内存的申请和释放,人不是完美的,所以会造成申请完内存不去释放的现象存在;
但是内存只申请不释放,到了一定的阶段,会造成我们的程序崩溃掉;
一般我们生产程序跑的时候,我们需要监控内存变化,如果内存可使用大幅度下降,很大概率是由于内存泄漏导致的,这时候,我们需要去定位分析内存泄漏的原因和修复;
二、案例
测试案例:
#include <iostream>
using namespace std;
void GetMemory(char* p,int num)
{
p = new char[sizeof(char)*num];
}
int main()
{
char* str = NULL;
while(1)
{
GetMemory(str,100);
}
return 0;
}
我们使用前面介绍过的命令看一下,内存的变化:
通过vmstat
命令,我们可以知道free
字段在逐渐减少,所以初步可以知道程序;
三、查找内存泄漏
1.valgrind
这是一款开源内存检测的工具,里面包含了很多的工具,一般使用Memcheck
这个工具偏多;
Memcheck
:这是valgrind
应用最广泛的工具,一个重量级的内存检查器,能够发现开发中绝大多数内存错误使用情况,比如:使用未初始化的内存,使用已经释放了的内存,内存访问越界等。
注:代码编译时我们要带上参数 -g
,有了符号表才可以显示行号这些东西;
测试代码就是我们上面的代码,我们把while
循环注释掉,会更好演示;
algrind --tool=memcheck --leak-check=full --show-reachable=yes --trace-children=yes ./tt
其中–leak-check=full 指的是完全检查内存泄漏,
–show-reachable=yes是显示内存泄漏的地点,
–trace-children=yes是跟入子进程。
结果:
我们会发现在第九行处出现了内存问题;
2.mtrace
mtrace
能监测程序是否内存泄露
mtrace
需要包含头文件:
#include <mcheck.h>
#include <stdlib.h>
步骤:
1.设置环境变量
setenv("MALLOC_TRACE", "output", 1);
2.调用mtrace
函数
mtrace();
代码:
#include <iostream>
#include <mcheck.h>
#include <stdlib.h>
using namespace std;
int main()
{
setenv("MALLOC_TRACE", "output", 1);
mtrace();
char* str = NULL;
//while(1)
{
char* p =(char*)malloc(12);
}
return 0;
}
3.编译(带 -g)
cmake_minimum_required (VERSION 2.8)
project (C++)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
add_executable(tt test.cpp)
4.运行
./tt
5.查看目录下
root@iZuf67on1pthsuih96udyfZ:~/C++/CMake/C++/Memory/build# ll
total 60
drwxr-xr-x 3 root root 4096 Apr 7 15:11 ./
drwxr-xr-x 3 root root 4096 Apr 7 15:04 ../
-rw-r--r-- 1 root root 11522 Apr 7 15:04 CMakeCache.txt
drwxr-xr-x 5 root root 4096 Apr 7 15:04 CMakeFiles/
-rw-r--r-- 1 root root 1369 Apr 7 15:04 cmake_install.cmake
-rw-r--r-- 1 root root 4681 Apr 7 15:04 Makefile
-rw-r--r-- 1 root root 313 Apr 7 15:11 output
-rwxr-xr-x 1 root root 18992 Apr 7 15:04 tt*
多了output文件
6.使用mtrace
命令,打开文件
root@iZuf67on1pthsuih96udyfZ:~/# mtrace test output
- 0x0000000001151c20 Free 3 was never alloc'd 0x7f863498ee9d
- 0x0000000001151d10 Free 4 was never alloc'd 0x7f8634a5991f
- 0x0000000001151d30 Free 5 was never alloc'd 0x7f8634ac923c
Memory not freed:
-----------------
Address Size Caller
0x00000000011521a0 0xc at /root/C++/CMake/C++/Memory/test.cpp:21
最终检测到了在21行出现了内存泄漏;
注:mtrace
只能检测new
是否有泄漏,但是不能定位在哪一行;
四、总结
作为一名合格的C/C++程序员,在编写程序的时候,我们需要牢记申请和释放内存,不然后造成想象不到的后果;