b4h*_*and 60
泄漏检测器有两种不同的工作方式.您可以在分配期间替换可以跟踪更多信息的实现,malloc并且free不关心性能.这与dmalloc工作方式类似.通常,任何malloc"但不是free"的地址都会泄露.
基本实现实际上非常简单.您只需维护每个分配及其行号的查找表,并在释放条目时删除该条目.然后当程序完成后,您可以列出所有泄漏的内存.困难的部分是确定应该释放分配的时间和地点.当有多个指向同一地址的指针时,这就更难了.
实际上,您可能不仅需要单行号,而且还需要丢失分配的堆栈跟踪.
另一种方法是valgrind如何工作,它实现整个虚拟机以跟踪地址和内存引用以及相关的簿记.valgrind方法更昂贵,但也更有效,因为它还可以告诉您其他类型的内存错误,如越界读取或写入.
Valgrind主要用于检测底层指令,并可以跟踪给定内存地址何时没有更多引用.它可以通过跟踪地址的分配做到这一点,因此它可以告诉你,不只是一块内存丢失了,但究竟何时它被湮灭.
C++使事情对于两种类型的泄漏检测的有点困难,因为它增加了new和delete运营商.技术上new可以是一个完全不同的内存来源malloc.但是,在实践中,许多真正的C++实现仅用于malloc实现new或具有使用选项malloc而不是替代方法.
此外,像C++这样的高级语言倾向于使用替代更高级别的方式来分配内存,如std::vector或std::list.基本的泄漏检测器将分别报告由更高级别模式进行的许多分配.这比说整个容器丢失要有用得多.
Ira*_*ter 19
这是一篇关于CheckPointer工具如何工作的已发表的技术论文.
从根本上说,它跟踪所有值(堆和堆栈)的生命周期,以及它们根据语言定义的类型的大小.这使得CheckPointer不仅可以查找泄漏,还可以查找数组外绑定访问,即使对于堆栈中的数组,valgrind也不会这样做.
特别是,它分析源代码以查找所有指针使用.(这本身就是一项任务).
它跟踪每个指针的指针元数据,包括
它还跟踪每个对象的类型和位置,即它是函数,全局,线程局部或局部变量,堆分配的内存还是字符串文字常量:
所有这些跟踪都是通过将原始程序源转换为执行原始程序所做的程序,并交错各种元数据检查或更新例程来完成的.生成的程序已编译并运行.如果元数据检查在运行时失败,则会提供回溯,其中包含失败类型的报告(无效指针,有效边界外的指针,......)
这是标记的C和C++,没有提到操作系统.这个答案适用于Windows.
Windows具有虚拟内存的概念.进程可以获得的任何内存都是虚拟内存.这是通过VirtualAlloc()[MSDN]完成的.您可以想象泄漏检测器在该函数上设置断点,并且无论何时调用它,它都会获取callstack并将其保存在某处.然后它可以为VirtualFree()[MSDN]做类似的事情.
然后可以识别差异并将其与已保存的callstack一起显示.
C++有一个不同的概念:它从VirtualAlloc()获取大的64kb块并将其拆分成更小的块,称为Heap.C++堆管理器来自Microsoft,提供新方法HeapAlloc()[MSDN]和HeapFree()[MSDN].
然后,您可以像以前一样做,但实际上,该功能已经内置.Microsoft的GFlags [MSDN]工具可以启用跟踪:

在这种情况下,它将为C++堆管理器调用保存多达50 MB的callstack信息.
由于也可以通过Windows注册表启用该设置,因此内存泄漏检测器可以轻松使用它.
正如您所看到的,一般概念是跟踪分配和解除分配,比较它们并显示差异的callstack.