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;
}



我们使用前面介绍过的命令看一下,内存的变化:




linux java堆内存工具 linux排查java内存泄露_内存泄漏


通过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是跟入子进程。

结果:


linux java堆内存工具 linux排查java内存泄露_valgrind 内存泄漏_02


我们会发现在第九行处出现了内存问题;


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++程序员,在编写程序的时候,我们需要牢记申请和释放内存,不然后造成想象不到的后果;