Mor*_*hai 6 c++ mfc memory-leaks memory-management
多年来我一直避免尝试使用operator new做任何事情,因为我觉得它在Windows上是一个泥潭(特别是使用MFC).更不用说,除非有一个非常令人信服的理由混淆全局(甚至是类)新的和删除,否则不应该.
但是,我有一个讨厌的小内存损坏错误,我非常想跟踪它.我从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有任何积极意义.
如何正确替换全局new和delete运算符
是否可以在MFC应用程序的调试版本中替换内存分配器?
我已经知道了:
好吧,它提供了它提供的功能 - 比如让我首先沿着这条路走下去的信息.我现在知道腐败正在发生,但这非常糟糕!
我想提供的是保护分配(或者甚至只是保护重新分配).这显然可以通过使用大量虚拟地址空间并将每个分配隔离开来,这极大地浪费了内存.好吧,是的,当这是一个仅用于调试的代码时,无法看到它的缺点,就像现在这样的特殊用途时刻一样.
所以,我正在拼命寻求以下解决方案
有没有人知道答案,或者阅读的好文章可能会说明如何实现这些目标?
其他想法:
进一步的调查:
2012年5月3日更新:
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 个块上中断!分配,因此,如果您可以获得相当一致的重现,因此每次都会损坏相同的数字块,那么您应该能够使用“第 n 个中断”功能来获取分配时的完整调用堆栈。
您可能还会发现_CrtCheckMemory
了解腐败是否更早发生的情况很有用。只需定期调用它,一旦您将错误括起来(错误没有发生在一个错误中,确实发生在另一个错误中),请将它们移得越来越近。