由于我觉得它在Windows上是一个泥潭(特别是使用MFC),因此我多年来一直避免尝试使用operator new做任何事情。更不用说,除非有一个非常令人信服的理由混淆全局(甚至是类)新的和删除,否则不应该。
然而,我有一个讨厌的小内存损坏错误,我非常想跟踪它。我从CRT调试分配器获取消息,指示先前释放的内存被覆盖。此消息仅在稍后的分配调用期间显示,当它尝试重用块时(无论如何,我相信这是它的工作方式)。
由于有问题的代码部分,错误消息和损坏点非常无关。我所知道的只是"某些东西覆盖了一些以前用一个空字节释放的内存。" (我通过使用调试器并在几次不同的运行中观察调试堆引用的内存来确定这一点。)
对于罪魁祸首可能出现的明显想法已经筋疲力尽,我离开了尝试做更严谨的事情。在我看来,如果我可以使每个释放的块成为无法访问的内存页面,那么编写器将立即被CPU的MMC捕获,这将是理想的!稍后再进行一些搜索,我发现有人在这些方面实施了一些东西:
http://www.codeproject.com/Articles/38340/Immediate-memory-corruption-detection
他的代码被埋没在大量的重新编码代码中,但提取核心概念非常简单,我已经这样做了。
我现在遇到的问题是MFC将新的redfines重新定义为DEBUG_NEW,然后进一步定义了一系列调试接口,直到CRT。此外,它确实定义了全局运算符new和delete。因此,就C ++而言,"用户"正在尝试将全局运算符new和delete两次替换,因此我在已定义的效果符号中出现了链接器错误。'
环顾互联网,以及SO,我看到了一些有前途的文章,但最终没有任何关于用MFC替换全局运算符new / delete的说法。
How to properly replace global new & delete operators
Is it possible to replace the memory allocator in a debug build of an MFC application?
我已经知道了:
嗯,它提供了它提供的内容 - 例如让我首先沿着这条路径滚动的消息。我现在知道腐败现象正在发生,但这种情况非常糟糕!
我想提供的是保护分配(甚至只是保护解除分配)。这显然可以通过使用大量虚拟地址空间并将每个分配隔离开来,这极大地浪费了内存。好的,是的,当这是一个仅用于调试的代码时,不能看到这样的特殊用途,就像现在一样。
所以,我正在拼命寻求以下解决方案
是否有人知道答案或阅读的好文章可能会说明如何实现这些目标?
其他想法:
进一步调查:
2012年5月3日更新:
答案 0 :(得分:4)
MSVCRT调试堆实际上非常好,并且有一些有用的功能,例如第n次分配的断点等。
http://msdn.microsoft.com/en-us/library/974tc9t1(v=VS.80).aspx
除此之外,你可以插入一个分配钩子,它输出调试信息等,你可以用来调试这类问题。
http://msdn.microsoft.com/en-us/library/z2zscsc2(v=vs.80).aspx
在您的情况下,您真正需要做的就是输出每个分配的地址,文件和行。然后,当您遇到损坏的块时,找到其地址紧接在其之前的块,这几乎肯定是覆盖的块。您可以使用Visual Studio调试器中的内存视图查看已损坏的内存地址,并查看前面的块。这应该告诉你需要知道的所有内容,以找出分配的时间。
调试堆在每个分配的块上也有一个数字分配ID,并且可以在第n个中断!分配,所以如果你可以获得一个相当一致的repro,那么每次都会损坏相同的数字块,那么你应该能够使用“break on nth”功能在分配时获得一个完整的调用堆栈。 / p>
您可能还会发现_CrtCheckMemory
有助于了解腐败是否发生得更早。只需定期调用它,一旦你把bug放在括号内(错误没有发生在一个中,确实发生在另一个中)将它们移得越来越近。