内存泄漏

背景


对于一个c/c++程序员来说,内存泄漏是一个常见的也是令人头疼的问题。已经有许多技术被研究出来以应对这个问题,比如 Smart Pointer,Garbage Collection等。Smart Pointer技术比较成熟,STL中已经包含支持Smart Pointer的class,但是它的使用似乎并不广泛,而且它也不能解决所有的问题;Garbage Collection技术在Java 中已经比较成熟,但是在c/c++领域的发展并不顺畅,虽然很早就有人思考在C++中也加入GC的支持。

内存泄露的定义


广义的内存泄露

​ 广义的说,内存泄漏不仅仅包含堆内存的泄漏,还包含系统资源的泄漏(resource leak),比如核心态HANDLE,GDI Object,SOCKET, Interface等,从根本上说这些由操作系统分配的对象也消耗内存,如果这些对象发生泄漏最终也会导致内存的泄漏。而且,某些对象消耗的是核心态内 存,这些对象严重泄漏时会导致整个操作系统不稳定。所以相比之下,系统资源的泄漏比堆内存的泄漏更为严重。

狭义的内存泄露

​ 一般我们常说的内存泄漏是指堆内存的泄漏。堆内存是指程序从堆中分配的,大小任意的(内存块的大小可以在程序运行期决定),使用完后必须显示释放的内 存。应用程序一般使用malloc,realloc,new等函数从堆中分配到一块内存,使用完后,程序必须负责相应的调用free或delete释放该 内存块,否则,这块内存就不能被再次使用,我们就说这块内存泄漏了。

一些概念


隐式内存泄漏

​ 程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存。但 是对于一个服务器程序,需要运行几天,几周甚至几个月,不及时释放内存也可能导致最终耗尽系统的所有内存。所以,我们称这类内存泄漏为隐式内存泄漏。

常见内些泄露相关问题


【内存泄露】内存(显存)未释放导致内存(显存)泄露

百度内部&业界内存泄漏检测工具


公司内部内存检测工具

  1. SA 静态扫描里面也有内存泄露的规则(较少,只有3条,可参考性较低);
  2. ASAN 用于运行时检测C/C++程序中的内存访问错误,使用的内存检测工具 Address Sanitizer (ASan)

业界内存检测工具


内存泄露检测工具总结

检测工具 分类 描述 性能影响 是否会修改源代码 能否指出具体位置和原因 应用场景 使用 备注
valgrind 动态检测 一个强大开源的程序检测工具 极大 适用Linux、Mac(Mac10.14后就不支持了) valgrind –tool=memcheck ./a.out 安装下载:https://www.valgrind.org详细使用:https://blog.csdn.net/andylauren/article/details/93189740原理介绍:https://blog.csdn.net/feisy/article/details/17022377
mtrace 动态检测 GNU扩展, 用来跟踪malloc, mtrace为内存分配函数(malloc, realloc, memalign, free)安装hook函数 适用Linux 无需安装,使用时包含头文件mcheck.h,程序中调用mtrace和muntrace方法即可。mtrace 用于开启内存使用记录,muntrace用于取消内存使用记录。内存使用情况记录到一个文件,值由环境变量:MALLOC_TRACE决定。 mtrace这个工具本身是 Glibc 的一部分,一般无须特殊安装详细使用:https://www.jianshu.com/p/d9e12b66096a原理介绍:https://zhuanlan.zhihu.com/p/83547768
splint 静态检测 一个针对C语言的开源程序静态分析工具 Linux、Windows 需要下载源码并安装程序,通过标志和注释来获取想要的错误信息splint *.c(Linux) 安装下载:http://splint.org/download.html详细使用:https://www.cnblogs.com/bangerlee/archive/2011/09/07/2166593.html
Gperftools heap-profiler 动态检测 是 google 开源的一个工具集 有消耗,较低 不能,需要自己分析输出的内存变化情况 适用Linux 需要替换libc的malloc库,替换为tcmalloc:thread cache malloc,通过在tcmalloc加打桩,即可定位函数级别的内存的累积量,需要自行分析内存变化情况找到内存泄露位置。 安装与详细使用:https://www.cnblogs.com/minglee/p/10124174.html
Visual Leak Detector 动态检测 免费的、开源的、强大的内存泄露检测系统,可以安装当作VS的一个插件。相比Visual C++自带的内存检测机制,Visual Leak Detector可以显示导致内存泄露的完整内存分配调用堆栈。 能指出位置,不能给原因 Visual C++ IDE上的工具 在安装完成后,在工程中指定其include和lib,然后添加头文件#include <vld.h>这样就可以使用了。 安装下载:https://blog.csdn.net/chaipp0607/article/details/79182471
Address Sanitizer (ASan) 动态检测 AddressSanitizer(内存错误检测器)最初由google研发,简称asan,用于运行时检测C/C++程序中的内存访问错误,相比较传统工具如valgind,运行速度快,检测到错误之后,输出信息非常详细,可以通过add2line符合输出,从而直接定位到代码行,方便快速的定位问题 有消耗,较低 Linux i386/x86_64 、OS X 10.7 - 10.11 (i386/x86_64)、iOS Simulator、Android ARM、FreeBSD i386/x86_64 gcc -fsanitize=address -ggdb -o test test.c编译后运行 详细使用:https://blog.csdn.net/yuanbinquan/article/details/106767635原理介绍:https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithm
CRT Visual C++ IDE 在程序退出前的最后一个地方调用_CrtDumpMemoryLeaks ()
BoundsChecker Visual C++ IDE
dmalloc 用于检查C/C++内存泄露(leak)的工具,即检查是否存在直到程序运行结束还没有释放的内存,以一个运行库的方式发布
memwatch 和dmalloc一样,它能检测未释放的内存、同一段内存被释放多次、位址存取错误及不当使用未分配之内存区域 在需要检测的.c文件里面包含memwatch.h文件,编译的时候加上几个参数即可
mpatrol 一个跨平台的 C++ 内存泄漏检测器