多年来,我一直避免尝试对 operator new 做任何事情,因为我觉得它在 Windows 上是一个泥潭(尤其是使用 MFC)。更不用说,除非有一个非常令人信服的理由来搞乱全局(甚至类)new 和 delete,否则不应该这样做。
但是,我有一个令人讨厌的小内存损坏错误,我非常想追踪它。我从 CRT 调试分配器收到消息,表明先前释放的内存已被覆盖。此消息仅在稍后的分配调用期间显示,当它尝试重用一个块时(我相信这就是它的工作方式,无论如何)。
由于有问题的代码部分,错误消息和损坏点非常不相关。我所知道的是“某处某处覆盖了一些以前用单个空字节释放的内存”。(我通过使用调试器并在几次不同的运行中观察调试堆引用的内存来确定这一点)。
在用尽了关于罪魁祸首可能在哪里的明显想法之后,我只能尝试做一些更严格的事情。我突然想到,如果我能让每个被释放的块变成一个不可访问的内存页面,这样写者就会立即被 CPU 的 MMC 捕获,那将是理想的!后来稍微搜索了一下,我发现有人按照这些思路实现了一些东西:
http://www.codeproject.com/Articles/38340/Immediate-memory-corruption-detection
他的代码隐藏在大量重复发明的代码中,但提取核心概念非常容易,我已经做到了。
我现在遇到的问题是 MFC 将 new 重新定义为 DEBUG_NEW,然后进一步定义了一系列到 CRT 的调试接口。此外,它确实定义了全局运算符 new 和 delete。因此,就 C++ 而言,“用户”试图替换全局运算符 new 并删除两次,因此我得到一个链接器错误,其效果为“符号已定义”。
环顾互联网,SO,我看到了一些有前途的文章,但没有一个最终对替换全球运营商 new/delete 为 MFC 有任何积极的看法。
如何正确替换全局新和删除运算符
是否可以在 MFC 应用程序的调试版本中替换内存分配器?
我已经意识到:
- MFC/CRT 已经为内存分配提供了丰富的调试工具。
好吧,它提供了它所提供的东西——比如让我一开始就沿着这条路走下去的信息。我现在知道正在发生腐败,但这是非常弱的酱汁!
我想提供的是保护分配(甚至只是保护释放)。这显然可以通过使用大量虚拟地址空间并将每个分配隔离起来,这非常浪费内存。好的,是的,当这是对像现在这样的特殊用途的时刻有用的仅调试代码时,看不到不利的一面。
因此,我正在拼命寻求以下解决方案
- 尽管 CRT/MFC 提供了一个,但强制编译器与我的全局运算符 new/delete 合作。
- 找到另一种方法来挂钩 MFC/CRT _heap_alloc_dbg 链,以使用我自己的代码代替他们的代码,以进行倒数第二次分配(即,我将通过操作系统的 VirtualAlloc/VirtualFree 分配以为 new 和/或马尔洛克)。
有没有人知道答案,或者阅读的好文章可能会阐明如何实现这些?
其他想法:
- 使用 thunk 技术在运行时替换 CRT 的 new/delete。
- 完全是其他一些方法?!
进一步的调查:
- 这篇文章很酷……它为我提供了一种在运行时修补全局 new/delete 运算符的方法。但是,正如文章指出的那样,它有点骇人听闻(但是,因为我只需要它来进行调试构建,这没什么大不了的)http://zeuxcg.blogspot.com/2009/03/fighting-against-crt- heap-and-winning.html
- 因此,尽管这达到了我想要的效果(一种替换 CRT 内存分配函数的机制),但这个实现已经过时了,到目前为止,我试图让它工作的尝试遇到了无数问题。我认为它对最初创建的版本太黑了,仅用于相对简单的控制台使用(即 C,甚至不是 C++,并且放弃了 microsoft CRT 提供的大多数调试功能)。因此,尽管这是一个非常酷的想法,但最终将花费大量时间来与当前的 VS2010 开发工作室合作,因此不值得(对我而言)。
- 显然,这个想法有一个众所周知的版本:http ://en.wikipedia.org/wiki/Electric_Fence不幸的是,即使是 Windows 端口,我也找到了http://code.google.com/p/electric-fence-win32 /未能正确覆盖 CRT,但要求您修改所有源代码以访问电子围栏堆分配代码。:(
2012 年 5 月 3 日更新:
- 现在我发现 Windows 已经提供了 Electric Fence 的实现,可以通过 GFLAGS 调试工具访问 http://support.microsoft.com/kb/286470 这可以在被测试的应用程序外部打开和关闭。它本质上与我感兴趣的技术相同,并且具有 DUMA 项目(电子围栏的一个分支 - http://duma.sourceforge.net/