我想知道是否有一个好的方法来找到导致堆损坏错误的源代码,给定在Visual Studio中分配的堆块“外部”写入的数据的内存地址;专用(0008)空闲列表元素26 F7 F670大小错误(无效)(试着写下一些关于如何查找内存错误的笔记)
pxiryf3j1#
开始安装windbg:http://www.microsoft.com/whdc/Devtools/Debugging/default.mspx然后像这样打开pageheap:
gflags.exe /p /enable yourexecutable.exe /full
这将在每次堆分配后插入一个不可写页。在从windbg内部启动可执行文件之后,任何堆外的写入都会被这个调试器捕获。要在之后打开页面堆,请使用以下命令:
gflags.exe /p /disable yourexecutable.exe
关于如何使用pageheap here的更多信息。
bz4sfanl2#
对于Windows 10,您可以启用PageHeap option in the GFlags Tool,此工具作为Debugging Tools for Windows的一部分包含在内。GFlags中的Page Heap选项允许您选择标准堆验证或整页堆验证。请注意,整页堆验证为每次分配使用整页内存,因此可能会导致系统内存不足。要在GFlags中启用页面堆,请执行以下操作:·要启用标准页堆验证,标准版本将在每次堆分配结束时写入模式,然后在分配释放时检查模式。要验证所有进程,请用途:
gflags /r +hpagflags /k +hpa
对于单一工艺用途:
gflags /p /enable ImageFileName
·若要为一个进程启用全页堆验证,此选项会在每次分配结束时放置一个不可访问的页,以便程序在尝试访问分配之外的内存时立即停止,由于内存消耗量很大,因此应仅在单个进程上使用此选项。
gflags /i ImageFileName +hpagflags /p /enable ImageFileName /full
上面的两个命令可以互换。
另一个有用的工具是Application Verifier,但这不是Windows调试工具的一部分,而是包含在Windows Software Development Kit (SDK)中。
7qhs6swi3#
也许你可以试试微软的Application Verifier。它曾经为我解决过一个类似的问题,通过对堆操作进行额外的检查。在我看来,损坏地址的随机性是因为堆可以“微妙地”损坏,问题不会出现,直到堆发生大的事情(比如大规模分配/释放)。
3ks5zfa04#
您可以在写入内存地址时设置断点。调试器将向您显示写入该位置的代码,但您仍然需要找出哪些写入导致了问题。
83qze16e5#
现在可能已经太晚了,但是如果它用gcc编译并且可以在linux上运行,你可以使用valgrind来找到问题的根源(我不记得标志了,我只用过一次,非常成功)。
fcwjkofz6#
关于Gflags和PageHeap的更多信息(这很有帮助):http://msdn.microsoft.com/en-us/library/windows/hardware/ff549561%28v=vs.85%29.aspx
k3bvogb17#
我假设C++作为语言。如果错误是可再现的,并且损坏的地址总是相同的,则可以在写入此地址时放置数据断点以停止程序。
gudnpqoy8#
确保您链接到的所有库都是在与您正在运行的应用程序相同的CLR版本中编译的-全部在Release中或全部在Debug中。
当你在Debug和Release中编译时,你实际上是在针对两个不同版本的C运行时库。这两个版本非常不同,它们使用不同的策略来分配内存,它们使用不同的堆。但最重要的是要知道它们彼此不兼容。Release C运行时库按预期分配内存,而Debug将添加额外的信息,例如用于跟踪缓冲区溢出的保护块和调用分配函数的位置,反过来它分配的内存比Release多。如果你将你的应用程序链接到一个混合的DLL,这些DLL是在发布和调试中构建的,你很可能最终试图删除一个CLR中的一个对象,而这个对象是在另一个CLR中创建的。这意味着你将试图释放比分配给对象的内存更多或更少的内存,这可能会破坏堆。您应该生成应用程序,并附加到在相同配置(发布或调试)下生成的库。这个问题尤其可能发生在使用不同编译器编译的模块中。有一种方法可以变通,我会提到但不推荐。如果出于某种原因你仍然需要在不同的模式下构建,这个变通方案将允许从同一个共享堆中分配和释放所有内存。API GetProcessHeap将允许你在不同的模块中访问共享堆。通过使用HeapAlloc & HeapFree你可以在共享堆中分配和释放内存。注意:HeapAlloc和HeapFree应该替换应用程序中所有对malloc和free的调用。
kmpatx3s9#
它救了我的命,我正在调试X-Plane 12堆损坏,这花了我一个星期的时间没有进展。gflags.exe位于C:\Program Files\Debugging Tools for Windows(x64)\gflags.exe并且必须以管理员身份运行,然后GUI图像输入使用X-Plane.exe,不要使用X-Plane.exe的路径。然后点击“启用页面堆”,最后应用。但是“启用页面堆”对你的情况来说太强了,因为它会消耗大量的内存好的,然后你可以像往常一样启动X-Plane 12,但是你会发现X-Plane的启动时间比以前要长得多,这不是调试目的的情况
9条答案
按热度按时间pxiryf3j1#
开始安装windbg:
http://www.microsoft.com/whdc/Devtools/Debugging/default.mspx
然后像这样打开pageheap:
这将在每次堆分配后插入一个不可写页。
在从windbg内部启动可执行文件之后,任何堆外的写入都会被这个调试器捕获。要在之后打开页面堆,请使用以下命令:
关于如何使用pageheap here的更多信息。
bz4sfanl2#
对于Windows 10,您可以启用PageHeap option in the GFlags Tool,此工具作为Debugging Tools for Windows的一部分包含在内。
GFlags中的Page Heap选项允许您选择标准堆验证或整页堆验证。请注意,整页堆验证为每次分配使用整页内存,因此可能会导致系统内存不足。
要在GFlags中启用页面堆,请执行以下操作:
·要启用标准页堆验证,标准版本将在每次堆分配结束时写入模式,然后在分配释放时检查模式。
要验证所有进程,请用途:
gflags /r +hpa
gflags /k +hpa
对于单一工艺用途:
gflags /p /enable ImageFileName
·若要为一个进程启用全页堆验证,此选项会在每次分配结束时放置一个不可访问的页,以便程序在尝试访问分配之外的内存时立即停止,由于内存消耗量很大,因此应仅在单个进程上使用此选项。
gflags /i ImageFileName +hpa
gflags /p /enable ImageFileName /full
上面的两个命令可以互换。
另一个有用的工具是Application Verifier,但这不是Windows调试工具的一部分,而是包含在Windows Software Development Kit (SDK)中。
7qhs6swi3#
也许你可以试试微软的Application Verifier。它曾经为我解决过一个类似的问题,通过对堆操作进行额外的检查。在我看来,损坏地址的随机性是因为堆可以“微妙地”损坏,问题不会出现,直到堆发生大的事情(比如大规模分配/释放)。
3ks5zfa04#
您可以在写入内存地址时设置断点。调试器将向您显示写入该位置的代码,但您仍然需要找出哪些写入导致了问题。
83qze16e5#
现在可能已经太晚了,但是如果它用gcc编译并且可以在linux上运行,你可以使用valgrind来找到问题的根源(我不记得标志了,我只用过一次,非常成功)。
fcwjkofz6#
关于Gflags和PageHeap的更多信息(这很有帮助):http://msdn.microsoft.com/en-us/library/windows/hardware/ff549561%28v=vs.85%29.aspx
k3bvogb17#
我假设C++作为语言。
如果错误是可再现的,并且损坏的地址总是相同的,则可以在写入此地址时放置数据断点以停止程序。
gudnpqoy8#
确保您链接到的所有库都是在与您正在运行的应用程序相同的CLR版本中编译的-全部在Release中或全部在Debug中。
当你在Debug和Release中编译时,你实际上是在针对两个不同版本的C运行时库。这两个版本非常不同,它们使用不同的策略来分配内存,它们使用不同的堆。但最重要的是要知道它们彼此不兼容。
Release C运行时库按预期分配内存,而Debug将添加额外的信息,例如用于跟踪缓冲区溢出的保护块和调用分配函数的位置,反过来它分配的内存比Release多。
如果你将你的应用程序链接到一个混合的DLL,这些DLL是在发布和调试中构建的,你很可能最终试图删除一个CLR中的一个对象,而这个对象是在另一个CLR中创建的。这意味着你将试图释放比分配给对象的内存更多或更少的内存,这可能会破坏堆。
您应该生成应用程序,并附加到在相同配置(发布或调试)下生成的库。
这个问题尤其可能发生在使用不同编译器编译的模块中。
有一种方法可以变通,我会提到但不推荐。如果出于某种原因你仍然需要在不同的模式下构建,这个变通方案将允许从同一个共享堆中分配和释放所有内存。API GetProcessHeap将允许你在不同的模块中访问共享堆。通过使用HeapAlloc & HeapFree你可以在共享堆中分配和释放内存。注意:HeapAlloc和HeapFree应该替换应用程序中所有对malloc和free的调用。
kmpatx3s9#
它救了我的命,我正在调试X-Plane 12堆损坏,这花了我一个星期的时间没有进展。
gflags.exe位于C:\Program Files\Debugging Tools for Windows(x64)\gflags.exe
并且必须以管理员身份运行,然后GUI图像输入使用X-Plane.exe,不要使用X-Plane.exe的路径。
然后点击“启用页面堆”,最后应用。但是“启用页面堆”对你的情况来说太强了,因为它会消耗大量的内存
好的,然后你可以像往常一样启动X-Plane 12,但是你会发现X-Plane的启动时间比以前要长得多,这不是调试目的的情况