有没有类似于Valgrind Memcheck的工具可以在Windows上调试use after free错误?

24
在工作中,我经常遇到常见的编程错误之一——使用已被释放的某个对象。这会在 C++ 中引起未定义行为。在Linux上,这种问题通常可以通过使用 Valgrind 工具 Memcheck 来解决。从Memcheck 手册中可以了解到:

Memcheck 试图确定非法地址可能涉及的内容,因为这通常很有用。所以,如果它指向已经被释放的内存块,您将会收到相关信息,并知道该内存块被释放的位置。

Memcheck 为我提供了调用堆栈,其中显示了释放该对象的位置,我可以继续调试问题。是否有类似的工具可以在 Windows 上实现相同的功能,最好是免费的?


我过去使用Purify的经验很好,但它肯定不是免费的。 - Mark B
2
https://dev59.com/JHRC5IYBdhLWcg3wFdFx - stanwise
如果你只对C语言的答案感兴趣,我有一个。 - Ira Baxter
5个回答

17

我已经尝试过AppVerifier,但它没有告诉我对象被释放的位置。 - ks1322
1
应用程序验证器应该使用完整的内存保护来捕获这个问题。当您释放对象时,它会保护已分配的页面,导致对其进行的任何未来操作都会引发异常。 - Collin Dauphinee
AppVerifier很烂,使用它运行程序会在Intel TBB代码中触发断点...这个程序很糟糕,但如果你禁用了那个检查,也许还可以。 - NoSenseEtAl

6

对我有用的方法是编写自定义内存管理器,提供全局操作符 "new" 和 "delete",并使用 VirtualProtect 锁定每个已释放或正在使用的内存块。这样,任何尝试使用已释放的内存都会立即触发访问冲突,您可以捕获并调试它。但是,为了能够做到这一点,您必须使用类似于 VirtualAlloc 的东西 "抓住" 所有可用内存(或其中的 3/4),并且您返回的每个内存块(从此最初分配的块中)必须是 PAGE_SIZE 对齐的(请参阅 GetSystemInfo 文档),否则您将无法可靠地锁定它。这意味着即使是微不足道的应用程序也可能需要大量内存才能使用此方法。

至于“Windows下的valgrind替代品”-我没有听说过。有人在某个地方发布说可能可以使用 cygwin 编译/使用 valgrind,但我不知道这是否为真。


5

以下是一个勇敢的Valgrind尝试,我祝他们一切顺利:

http://sourceforge.net/p/valgrind4win/wiki/Home/

然而,为了实现适用于Windows的正确的“Valgrind”,需要访问Windows源代码。

也就是说:除非猪会飞。


2
为什么需要访问Windows源代码? - Jeff

5
根据Dr. Memory文档,有一个名为-delay_frees_stack的选项,其功能与Valgrind完全相同。来自选项参考页面的说明:
-delay_frees_stack 
default: false 
Record callstacks on free to use when reporting use-after-free or other errors that overlap with freed objects. There is a slight performance hit incurred by this feature for malloc-intensive applications.

下面是Dr. Memory报告的一个错误示例

Here is another example, using the -delay_frees_stack option to obtain the callstack of the freed memory:

Error #8: UNADDRESSABLE ACCESS: reading 0x001338a8-0x001338ac 4 byte(s)
# 0 unaddr_test1                    [e:\derek\drmemory\git\src\tests\suppress.c:110]
# 1 test                            [e:\derek\drmemory\git\src\tests\suppress.c:269]
# 2 main                            [e:\derek\drmemory\git\src\tests\suppress.c:297]
Note: @0:00:02.141 in thread 3024
Note: next higher malloc: 0x001338e8-0x00133938
Note: prev lower malloc:  0x001337e8-0x00133820
Note: 0x001338a8-0x001338ac overlaps memory 0x001338a8-0x001338c4 that was freed here:
Note: # 0 test                            [e:\derek\drmemory\git\src\tests\suppress.c:269]
Note: # 1 main                            [e:\derek\drmemory\git\src\tests\suppress.c:297]
Note: instruction: mov    (%eax) -> %eax

3

对我来说最有效的方法是使用Visual leak Detector,我所需要做的就是包含:

#include <vld.h>

我想在测试可执行文件时添加内存泄漏检测功能。然后,在Windows系统中运行调试可执行文件时,会提供有关所有泄漏内存的详细信息。从输出结果中,您可以直接找到内存分配的代码行,以便进行修复。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接