使用 Valgrind 检测 C++ 内存泄漏

Valgrind 的介绍

  Valgrind 可以用来检测程序是否有非法使用内存的问题,例如访问未初始化的内存、访问数组时越界、忘记释放动态内存等问题。在 Linux 可以使用下面的命令安装 Valgrind:


1

2

3

4

5

6


$ wget ftp://sourceware.org/pub/valgrind/valgrind-3.13.0.tar.bz2

$ bzip2 -d valgrind-3.13.0.tar.bz2

$ tar -xf valgrind-3.13.0.tar

$ cd valgrind-3.13.0

$ ./configure && make

$ sudo make install

检测内存泄漏

  Valgrind 可以用来检测程序在哪个位置发生内存泄漏,例如下面的程序:


1

2

3

4

5

6

7

8


#include <stdlib.h>

int main()

{

int *array = malloc(sizeof(int));

return 0;

}

  编译程序时,需要加上-g选项:


1

$ gcc -g -o main_c main.c

  使用 Valgrind 检测内存使用情况:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24


$ valgrind --tool=memcheck --leak-check=full ./main_c

==31416== Memcheck, a memory error detector

==31416== Copyright (C) 2002-2017, and GNU GPL‘d, by Julian Seward et al.

==31416== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info

==31416== Command: ./main_c

==31416==

==31416==

==31416== HEAP SUMMARY:

==31416== in use at exit: 4 bytes in 1 blocks

==31416== total heap usage: 1 allocs, 0 frees, 4 bytes allocated

==31416==

==31416== 4 bytes in 1 blocks are definitely lost in loss record 1 of 1

==31416== at 0x4C2DBF6: malloc (vg_replace_malloc.c:299)

==31416== by 0x400537: main (main.c:5)

==31416==

==31416== LEAK SUMMARY:

==31416== definitely lost: 4 bytes in 1 blocks

==31416== indirectly lost: 0 bytes in 0 blocks

==31416== possibly lost: 0 bytes in 0 blocks

==31416== still reachable: 0 bytes in 0 blocks

==31416== suppressed: 0 bytes in 0 blocks

==31416==

==31416== For counts of detected and suppressed errors, rerun with: -v

==31416== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

  先看看输出信息中的HEAP SUMMARY,它表示程序在堆上分配内存的情况,其中的1 allocs表示程序分配了 1 次内存,0 frees表示程序释放了 0 次内存,4 bytes allocated表示分配了 4 个字节的内存。
  另外,Valgrind 也会报告程序是在哪个位置发生内存泄漏。例如,从下面的信息可以看到,程序发生了一次内存泄漏,位置是main.c文件的第 5 行:


1

2

3


==31416== 4 bytes in 1 blocks are definitely lost in loss record 1 of 1

==31416== at 0x4C2DBF6: malloc (vg_replace_malloc.c:299)

==31416== by 0x400537: main (main.c:5)



  Valgrind 也可以用来检测 C++ 程序的内存泄漏,下面是一个正常的 C++ 程序,没有发生内存泄漏:


1

2

3

4

5

6

7

8

9


#include <string>

int main()

{

auto ptr = new std::string("Hello, World!");

delete ptr;

return 0;

}

  使用 Valgrind 分析这段程序:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28


$ valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all ./main_cpp

==31438== Memcheck, a memory error detector

==31438== Copyright (C) 2002-2017, and GNU GPL‘d, by Julian Seward et al.

==31438== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info

==31438== Command: ./main_cpp

==31438==

==31438==

==31438== HEAP SUMMARY:

==31438== in use at exit: 72,704 bytes in 1 blocks

==31438== total heap usage: 2 allocs, 1 frees, 72,736 bytes allocated

==31438==

==31438== 72,704 bytes in 1 blocks are still reachable in loss record 1 of 1

==31438== at 0x4C2DBF6: malloc (vg_replace_malloc.c:299)

==31438== by 0x4EC3EFF: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)

==31438== by 0x40104E9: call_init.part.0 (dl-init.c:72)

==31438== by 0x40105FA: call_init (dl-init.c:30)

==31438== by 0x40105FA: _dl_init (dl-init.c:120)

==31438== by 0x4000CF9: ??? (in /lib/x86_64-linux-gnu/ld-2.23.so)

==31438==

==31438== LEAK SUMMARY:

==31438== definitely lost: 0 bytes in 0 blocks

==31438== indirectly lost: 0 bytes in 0 blocks

==31438== possibly lost: 0 bytes in 0 blocks

==31438== still reachable: 72,704 bytes in 1 blocks

==31438== suppressed: 0 bytes in 0 blocks

==31438==

==31438== For counts of detected and suppressed errors, rerun with: -v

==31438== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

  使用 Valgrind 分析 C++ 程序时,有一些问题需要留意。例如,这个程序并没有发生内存泄漏,但是从HEAP SUMMARY可以看到,程序分配了 2 次内存,但却只释放了 1 次内存,为什么会这样呢?
  实际上这是由于 C++ 在分配内存时,为了提高效率,使用了它自己的内存池。当程序终止时,内存池的内存才会被操作系统回收,所以 Valgrind 会将这部分内存报告为 reachable 的,需要注意,reachable 的内存不代表内存泄漏,例如,从上面的输出中可以看到,有 72704 个字节是 reachable 的,但没有报告内存泄漏。

检测越界访问

  C++ 程序经常出现的 Bug 就是数组越界访问,例如下面的程序出现了越界访问:


1

2

3

4

5

6

7

8

9

10


#include <vector>

#include <iostream>

int main()

{

std::vector<int> v(10, 0);

std::cout << v[10] << std::endl;

return 0;

}

  使用 Valgrind 分析这段程序,Valgrind 会提示越界访问:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18


$ g++ -std=c++11 -g -o main_cpp main.cpp

$ valgrind --tool=memcheck --leak-check=full ./main_cpp

==31523== Memcheck, a memory error detector

==31523== Copyright (C) 2002-2017, and GNU GPL‘d, by Julian Seward et al.

==31523== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info

==31523== Command: ./main_cpp

==31523==

==31523== Invalid read of size 4

==31523== at 0x400AD7: main (main.cpp:7)

==31523== Address 0x5ab5ca8 is 0 bytes after a block of size 40 alloc‘d

==31523== at 0x4C2E216: operator new(unsigned long) (vg_replace_malloc.c:334)

==31523== by 0x4010D3: __gnu_cxx::new_allocator<int>::allocate(unsigned long, void const*) (new_allocator.h:104)

==31523== by 0x401040: std::allocator_traits<std::allocator<int> >::allocate(std::allocator<int>&, unsigned long) (alloc_traits.h:491)

==31523== by 0x400F91: std::_Vector_base<int, std::allocator<int> >::_M_allocate(unsigned long) (stl_vector.h:170)

==31523== by 0x400E7E: std::_Vector_base<int, std::allocator<int> >::_M_create_storage(unsigned long) (stl_vector.h:185)

==31523== by 0x400D1E: std::_Vector_base<int, std::allocator<int> >::_Vector_base(unsigned long, std::allocator<int> const&) (stl_vector.h:136)

==31523== by 0x400C11: std::vector<int, std::allocator<int> >::vector(unsigned long, int const&, std::allocator<int> const&) (stl_vector.h:291)

==31523== by 0x400AB9: main (main.cpp:6)

  Invalid read of size 4表示越界读取 4 个字节,这个操作出现在main.cpp文件的第 7 行。另外可以看到,vector分配了一块 40 字节的内存,程序越界访问紧急着这块内存之后的 4 个字节。

检测未初始化的内存

  另一种经常出现的 Bug,就是程序访问了未初始化的内存。例如:


1

2

3

4

5

6

7

8

9

10

11

12


#include <iostream>

int main()

{

int x;

if (x == 0)

{

std::cout << "X is zero" << std::endl;

}

return 0;

}

  使用 Valgrind 检测这个程序:


1

2

3

4

5

6

7

8

9


$ g++ -std=c++11 -g -o main_cpp main.cpp

$ valgrind --tool=memcheck --leak-check=full ./main_cpp

==31554== Memcheck, a memory error detector

==31554== Copyright (C) 2002-2017, and GNU GPL‘d, by Julian Seward et al.

==31554== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info

==31554== Command: ./main_cpp

==31554==

==31554== Conditional jump or move depends on uninitialised value(s)

==31554== at 0x400852: main (main.cpp:6)

  输出中提示了main.cpp文件的第 6 行访问了未初始化的内存。

原文地址:https://www.cnblogs.com/qiumingcheng/p/11318637.html

时间: 2024-10-31 20:30:01

使用 Valgrind 检测 C++ 内存泄漏的相关文章

使用Valgrind检测DPDK内存泄漏

直接用valgrind检测使用dpdk库的程序可能会报错 如: ERROR: This system does not support "RDRAND". Please check that RTE_MACHINE is set correctly. 解决办法: 禁用CPUd RDRAND 修改mk/rte.cpuflags.mk, 注释掉CPUFLAGS += RDRAND,重新编译库即可 原文地址:https://www.cnblogs.com/zl-yang/p/9932791.

valgrind 代码检查,内存泄漏

使用平台 linux 下载 http://valgrind.org/ 文档 http://valgrind.org/docs/manual/manual.html 博客 https://www.oschina.net/translate/valgrind-memcheck https://blog.csdn.net/justheretobe/article/details/52986461 原文地址:https://www.cnblogs.com/scotth/p/10916466.html

C++内存泄漏检测工具

C++内存泄漏检测工具 1.VC自带的CRT:_CrtCheckMemory   调试器和 CRT 调试堆函数 1.1用法: /************************************************************************ * 环境:VC6.0 * 程序功能:CRT 检测内存泄漏 * 创建: 2014/3/20 * 版本号:1.0 **********************************************************

基于Android Studio的内存泄漏检测与解决全攻略

自从Google在2013年发布了Android Studio后,Android Studio凭借着自己良好的内存优化,酷炫的UI主题,强大的自动补全提示以及Gradle的编译支持正逐步取代Eclipse,成为主流的Android开发IDE.Android Studio在为我们提供了良好的编码体验的同时,也提供了许多对App性能分析的工具,让开发者可以更方便分析App性能.Google在IO大会上一直告诫开发者不要无节制的使用手机内存,要注意一些不良的开发习惯会导致App的内存泄漏.虽然如今网上

Android 性能优化之内存泄漏检测以及内存优化(上)

在 Java 中,内存的分配是由程序完成的,而内存的释放则是由 Garbage Collecation(GC) 完成的,Java/Android 程序员不用像 C/C++ 程序员一样手动调用相关函数来管理内存的分配和释放,虽然方便了很多,但是这也就造成了内存泄漏的可能性,所以记录一下针对 Android 应用的内存泄漏的检测,处理和优化的相关内容,上篇主要会分析 Java/Android 的内存分配以及 GC 的详细分析,中篇会阐述 Android 内存泄漏的检测和内存泄漏的常见产生情景,下篇会

使用 Android Studio 检测内存泄漏与解决内存泄漏问题

自从Google在2013年发布了Android Studio后,Android Studio凭借着自己良好的内存优化,酷炫的UI主题,强大的自动补全提示以及Gradle的编译支持正逐步取代Eclipse,成为主流的Android开发IDE.Android Studio在为我们提供了良好的编码体验的同时,也提供了许多对App性能分析的工具,让开发者可以更方便分析App性能.Google在IO大会上一直告诫开发者不要无节制的使用手机内存,要注意一些不良的开发习惯会导致App的内存泄漏.虽然如今网上

android 内存泄漏检测工具 LeakCanary 泄漏金丝雀

韩梦飞沙 yue31313 韩亚飞 han_meng_fei_sha [email protected] 内存泄漏检测工具 android 内存泄漏检测工具 ======== 内存泄漏 就是  无用的对象没有被回收,占用着内存,使得可用内存变小了. 如何检测内存泄漏, 可以使用 LeakCanary来检测内存泄漏. leak  是 泄漏的意思.. Canary 是 金丝雀 的意思. 在运行 应用的时候, 泄漏金丝雀 如果检测到内存泄漏 会显示一个通知. ======== LeakCanary捕获

如何在linux下检测内存泄漏(转)

本文转自:http://www.ibm.com/developerworks/cn/linux/l-mleak/ 本文针对 linux 下的 C++ 程序的内存泄漏的检测方法及其实现进行探讨.其中包括 C++ 中的 new 和 delete 的基本原理,内存检测子系统的实现原理和具体方法,以及内存泄漏检测的高级话题.作为内存检测子系统实现的一部分,提供了一个具有更好的使用特性的互斥体(Mutex)类. 1.开发背景 在 windows 下使用 VC 编程时,我们通常需要 DEBUG 模式下运行程

Linux-3.14.12内存管理笔记【内存泄漏检测kmemleak示例】【转】

本文转载自:http://blog.chinaunix.net/uid-26859697-id-5758037.html 分析完kmemleak实现后,照常实验一下,以确定功能正常. 如kmemcheck一样,该功能需要在内核开启的情况下才能够使用.主要的配置项有:CONFIG_DEBUG_KERNEL.CONFIG_HAVE_DEBUG_KMEMLEAK.CONFIG_DEBUG_KMEMLEAK,以及配置信息记录条数的CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE,