当前位置: 首页 > news >正文

内存泄漏检测之Valgrind的使用

工具介绍

Valgrind 是 Linux 下强大的内存调试和性能分析工具,其 Memcheck 工具可以有效检测内存泄漏。

Linux下的安装

Ubuntu下

sudo apt update
sudo apt install valgrind

CentOS下

sudo yum install valgrind

Valgrind的使用

测试代码

#include<iostream>
#include <vector>
#include<memory>
using namespace std;class base{
private:int *a;
public:base(int a): a(new int(a)){cout<<"base 构造函数调用!"<<endl;}~base(){/*delete a;*/}
};class ptr_B;class ptr_A{
private :public:shared_ptr<ptr_B> b;ptr_A(){cout<<"ptr_A构造函数调用"<<endl;}
};class ptr_B{
private:public:shared_ptr<ptr_A> a;ptr_B(){cout<<"ptr_B构造函数调用"<<endl;}
};int main(){//常规动态分配内存忘了deleteint *testA=new int(0);//类的构造忘了析构base b=base(1);//shared_ptr的循环引用shared_ptr<ptr_A> testPtr_A= make_shared<ptr_A>();shared_ptr<ptr_B> testPtr_B= make_shared<ptr_B>();testPtr_A->b=testPtr_B;    testPtr_B->a=testPtr_A;cout<<"代码运行结束!Good Luck!"<<endl;return 0;
}

编译程序时添加调试信息

g++ -g -o0 test.cpp -o test

使用 Valgrind 运行程序

valgrind --leak-check=full --show-leak-kinds=all ./test 
  • --leak-check=full:全面检查内存泄漏

  • --show-leak-kinds=all:显示所有泄漏类型(包括可能的和确定的)

关键选项说明

--leak-check=full :详细分析内存泄漏,显示泄漏的内存块位置

--show-leak-kinds=all : 显示所有泄漏类型: - `definite`:确定的泄漏

                                                                           - `possible`:可能的泄漏                             

                                                                           - `indirect`:间接泄漏

                                                                          - `still-reachable`:未释放但仍可访问

--track-origins=yes  :跟踪未初始化变量的来源(定位使用未初始化值的错误)

--log-file=valgrind.log :将输出结果保存到文件

--num-callers=20 :显示堆栈回溯的深度(默认 12 层)

--suppressions=file.supp ​​​​​​​:忽略特定类型的错误(如第三方库的误报)

valgrind --tool=massif ./test :按照时间来分析堆上的内容数据变化,每隔一段时间拍快照

结果分析

分析内容在“ # ”后面


valgrind运行结果:
==9968== Memcheck, a memory error detector
==9968== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==9968== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==9968== Command: ./test
==9968== 
base 构造函数调用!
ptr_A构造函数调用
ptr_B构造函数调用
代码运行结束!Good Luck!
==9968== 
==9968== HEAP SUMMARY:
==9968==     in use at exit: 72 bytes in 4 blocks    #退出时仍然后4个内存处于使用状态,共占用72字节的堆内存!也就是内存泄漏
==9968==   total heap usage: 6 allocs, 2 frees, 73,800 bytes allocated  #整个运行过程中,堆进行了6次的分配操作,2次释放操作
==9968== 
==9968== 4 bytes in 1 blocks are definitely lost in loss record 1 of 4   #第一个泄露的地方
==9968==    at 0x483BE63: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==9968==    by 0x1092CD: main (test.cpp:39)   							#第39行的new 操作没有delete
==9968== 
==9968== 4 bytes in 1 blocks are definitely lost in loss record 2 of 4	#第二个泄漏的地方
==9968==    at 0x483BE63: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==9968==    by 0x10961A: base::base(int) (test.cpp:10)
==9968==    by 0x1092E8: main (test.cpp:43)								#main函数43行中base的构造函数,中间的new操作没有delete
==9968== 
==9968== 32 bytes in 1 blocks are indirectly lost in loss record 3 of 4		#第三个泄漏的地方   表示存在间接内存泄漏,总结来就是循环引用
==9968==    at 0x483BE63: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==9968==    by 0x10AAE9: __gnu_cxx::new_allocator<std::_Sp_counted_ptr_inplace<ptr_B, std::allocator<ptr_B>, (__gnu_cxx::_Lock_policy)2> >::allocate(unsigned long, void const*) (new_allocator.h:114)
==9968==    by 0x10A882: std::allocator_traits<std::allocator<std::_Sp_counted_ptr_inplace<ptr_B, std::allocator<ptr_B>, (__gnu_cxx::_Lock_policy)2> > >::allocate(std::allocator<std::_Sp_counted_ptr_inplace<ptr_B, std::allocator<ptr_B>, (__gnu_cxx::_Lock_policy)2> >&, unsigned long) (alloc_traits.h:443)
==9968==    by 0x10A4A7: std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<ptr_B, std::allocator<ptr_B>, (__gnu_cxx::_Lock_policy)2> > > std::__allocate_guarded<std::allocator<std::_Sp_counted_ptr_inplace<ptr_B, std::allocator<ptr_B>, (__gnu_cxx::_Lock_policy)2> > >(std::allocator<std::_Sp_counted_ptr_inplace<ptr_B, std::allocator<ptr_B>, (__gnu_cxx::_Lock_policy)2> >&) (allocated_ptr.h:97)
==9968==    by 0x10A0AD: std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<ptr_B, std::allocator<ptr_B>>(ptr_B*&, std::_Sp_alloc_shared_tag<std::allocator<ptr_B> >) (shared_ptr_base.h:677)
==9968==    by 0x109ECF: std::__shared_ptr<ptr_B, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<ptr_B>>(std::_Sp_alloc_shared_tag<std::allocator<ptr_B> >) (shared_ptr_base.h:1344)
==9968==    by 0x109DC4: std::shared_ptr<ptr_B>::shared_ptr<std::allocator<ptr_B>>(std::_Sp_alloc_shared_tag<std::allocator<ptr_B> >) (shared_ptr.h:359)
==9968==    by 0x109C7D: std::shared_ptr<ptr_B> std::allocate_shared<ptr_B, std::allocator<ptr_B>>(std::allocator<ptr_B> const&) (shared_ptr.h:702)
==9968==    by 0x1099DB: std::shared_ptr<ptr_B> std::make_shared<ptr_B>() (shared_ptr.h:718)
==9968==    by 0x109300: main (test.cpp:47)
==9968== 
==9968== 64 (32 direct, 32 indirect) bytes in 1 blocks are definitely lost in loss record 4 of 4  #第四个地方
==9968==    at 0x483BE63: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==9968==    by 0x10A9CD: __gnu_cxx::new_allocator<std::_Sp_counted_ptr_inplace<ptr_A, std::allocator<ptr_A>, (__gnu_cxx::_Lock_policy)2> >::allocate(unsigned long, void const*) (new_allocator.h:114)
==9968==    by 0x10A6FC: std::allocator_traits<std::allocator<std::_Sp_counted_ptr_inplace<ptr_A, std::allocator<ptr_A>, (__gnu_cxx::_Lock_policy)2> > >::allocate(std::allocator<std::_Sp_counted_ptr_inplace<ptr_A, std::allocator<ptr_A>, (__gnu_cxx::_Lock_policy)2> >&, unsigned long) (alloc_traits.h:443)
==9968==    by 0x10A235: std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<ptr_A, std::allocator<ptr_A>, (__gnu_cxx::_Lock_policy)2> > > std::__allocate_guarded<std::allocator<std::_Sp_counted_ptr_inplace<ptr_A, std::allocator<ptr_A>, (__gnu_cxx::_Lock_policy)2> > >(std::allocator<std::_Sp_counted_ptr_inplace<ptr_A, std::allocator<ptr_A>, (__gnu_cxx::_Lock_policy)2> >&) (allocated_ptr.h:97)
==9968==    by 0x109F3B: std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<ptr_A, std::allocator<ptr_A>>(ptr_A*&, std::_Sp_alloc_shared_tag<std::allocator<ptr_A> >) (shared_ptr_base.h:677)
==9968==    by 0x109E7B: std::__shared_ptr<ptr_A, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<ptr_A>>(std::_Sp_alloc_shared_tag<std::allocator<ptr_A> >) (shared_ptr_base.h:1344)
==9968==    by 0x109D7A: std::shared_ptr<ptr_A>::shared_ptr<std::allocator<ptr_A>>(std::_Sp_alloc_shared_tag<std::allocator<ptr_A> >) (shared_ptr.h:359)
==9968==    by 0x109C11: std::shared_ptr<ptr_A> std::allocate_shared<ptr_A, std::allocator<ptr_A>>(std::allocator<ptr_A> const&) (shared_ptr.h:702)
==9968==    by 0x109951: std::shared_ptr<ptr_A> std::make_shared<ptr_A>() (shared_ptr.h:718)
==9968==    by 0x1092F4: main (test.cpp:46)
==9968== 
==9968== LEAK SUMMARY:
==9968==    definitely lost: 40 bytes in 3 blocks   #确定的内存泄漏
==9968==    indirectly lost: 32 bytes in 1 blocks	#不确定的间接内存泄漏
==9968==      possibly lost: 0 bytes in 0 blocks
==9968==    still reachable: 0 bytes in 0 blocks
==9968==         suppressed: 0 bytes in 0 blocks
==9968== 
==9968== For lists of detected and suppressed errors, rerun with: -s
==9968== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)

相关文章:

  • c++数据结构7——二叉树的遍历
  • 从实验室到商用!铁电液晶如何改写显示技术格局?
  • IT Tools 部署
  • 20中数组去重的方法20种数组去重的方法
  • 【数学】求最大公约数问题
  • 贝锐蒲公英工业路由器R300A海外版:支持多国4G频段,全球组网
  • Cadence Allegro中设置主画面最小显示间距
  • JAVA:Kafka 消息可靠性详解与实践样例
  • 常见关系型数据库对比指南
  • 【Linux笔记】Shell-脚本(下)|(常用命令详细版)
  • 利用Python制作环保志愿者招募海报
  • echarts主题切换实现
  • 容器(如 Docker)中,通常不建议运行多个进程或要求进程必须运行在前台
  • 物联网常用协议Modbus、CAN、BACnet介绍
  • 【C语言】指针详解(接)
  • vue发版html 生成打包到docker镜像进行发版
  • 《深度关系-从建立关系到彼此信任》
  • 【android bluetooth 协议分析 02】【bluetooth hal 层详解 6】【bt_vendor_opcode_t 介绍】
  • Ad Hoc
  • 源的企业级网络安全检测工具Prism X(棱镜X)
  • 群辉做网站服务器/长治seo顾问
  • 家庭宽带 用443端口做网站/4p营销理论
  • 做网站用.net还是java/官网整站优化
  • 网站做标题有用吗/医疗器械龙头股
  • 百度网站排名优化软件/智能建站模板
  • 网站跟web的区别/现在的seo1发布页在哪里