美文网首页
内存泄漏检测工具 memcheck

内存泄漏检测工具 memcheck

作者: wayyyy | 来源:发表于2020-07-19 22:42 被阅读0次

valgrind

valgrind是运行在Linux上一套基于仿真技术的程序调试和分析工具,它包含一个内核,一个软件合成的CPU,和一系列的小工具,每个工具都可以完成一项任务──调试,分析,或测试等。

官方文档:https://www.valgrind.org/docs/manual/manual.html

valgrind 体系结构.png

这里我们重点介绍:memcheck 是一个细粒度的的内存检查器。


安装

这里我们将valgrind安装在/usr/local/valgrind目录下面。

mkdir tmp
wget http://www.valgrind.org/downloads/valgrind-3.14.0.tar.bz2
tar -jxvf valgrind-3.14.0.tar.bz2
./configure --prefix=/usr/local/valgrind
make
make install
  • 配置环境变量
    vim 编辑~/.bashrc文件
    vim ~/.bashrc
    
    加入下面这段内容
    export PATH=$PATH:/usr/local/valgrind/bin/
    
    使改变生效
    source ~/.bashrc
    

常见内存错误

  • 未初始化内存
  • 内存读写越界
  • 内存覆盖
  • 动态内存管理错误
  • 内存泄漏

使用命令格式

valgrind --tool=toolname args-val program args-pro
  • --tool用于选择valgrind tool中的一种,后面接tool的名字。可以不加这个参考,则默认使用memcheck。
  • atgs-val 指valgrind可以添加的参数,用于配置单次运行时的特殊需求,可以通过valgrind -h查看参数的各类的作用。
  • program用于指定检测程序对象,valgrind对目标program的编译过程有些要求:
    • 打开调试模式-g,否则难以输出问题代码的具体行数。
    • 关闭编译优化选项
memcheck命令
  • memcheck 命令
    valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all ./a.out 
    
  • 结束 Memcheck 检查的做法一般是发送 SIGINT 信号,即ctrl + c。不要发送 SIGKILL 信号结束进程,否则无法生成检查报告。
  • 使用valgrind会导致可执行文件的速度减慢 20 至 30 倍。

输出报告内容分析

memcheck 输出结果会报告5种内存泄露:

definitely lost 和 still reachable

definitely lost
表示确认丢失,程序中存在内存泄露,应尽快修复。当程序结束时如果一块动态分配的内存没有被释放且通过程序内的指针变量均无法访问这块内存则会报这个错误。

still reachable

void test01() { char *p = new char[1024];  }
void test02()  {  static char* p = new char[1024];}

int main()
{
    test01();
    test02();
}
image.png
indirectly lost

间接丢失。当使用了含有指针成员的类或结构时可能会报这个错误。这类错误无需直接修复,他们总是与definitely lost一起出现,只要修复definitely lost即可

class Object {
public:
    Object() { _p = new char[1024]; }
    ~Object() { if(_p) delete _p; }
private:
    char* _p = nullptr;
};

void test03() {  Object* obj = new Object();  };

int main() 
{
    test03();
    return 0;
}
image.png
possibly lost

可能丢失。大多数情况下应视为与definitely lost一样需要尽快修复,除非你的程序让一个指针指向一块动态分配的内存(但不是这块内存起始地址)

  • 示例一

    void test04()
    {
        char* data = new char[1024];
        static char* p = data + 1;
    }
    int main()
    {  
        test04();
    }
    
    image.png
    test04 测试结束后直到 main 函数返回前,静态指针 p 仍然可获得,但是 p 已经不再指向数组的起始地址。Memcheck 认为指向这块内存的指针可能已经丢失,会报告 possibly lost 错误。
  • 示例2

    void test04() 
    {
        char* data = new char[1024];
        static char* p = data + 1;
        p = data;
    }
    

    此时,静态指针 p 重新指向了数组的起始地址,所以 Memcheck 不会再报告 possibly lost 错误。但是 Memcheck 会报告 still reachable 错误,这是因为静态指针指向的数组空间没有被释放,在测试进程结束前仍然可以获取到导致。

  • 示例3

    void test04() {
        char* data = new char[1024];
        staticchar* p = data + 1;
        p = data;
        p = nullptr;
    }
    

    在 test04 函数中再增加一行代码 p = nullptr
    Memcheck 会输出 definitely lost 错误。
    因为 p 为空指针,不指向任何已分配的内存块,且没有指向数组的非起始地址,所以不会有 still reachablepossibly lost 这两种错误。

suppressed

已被解决。出现了内存泄露但系统自动处理了,可以无视这类错误。


参考资料

  1. https://www.ibm.com/developerworks/cn/linux/l-cn-valgrind/
  2. https://windmissing.github.io/linux/2016-02/valgrind-memcheck.html
  3. https://mp.weixin.qq.com/s/VH740i8H4UfHWkzpO5QoTA

相关文章

网友评论

      本文标题:内存泄漏检测工具 memcheck

      本文链接:https://www.haomeiwen.com/subject/tlffvhtx.html