我想知道在Visual Studio中,是否有一种好的方法可以找到导致堆栈损坏错误的源代码,只给出写入“外部”的内存地址;
专用(0008)自由列表元素26F7F670的大小不正确(已死亡)
(试图记录如何查找内存错误的笔记)
我想知道在Visual Studio中,是否有一种好的方法可以找到导致堆栈损坏错误的源代码,只给出写入“外部”的内存地址;
专用(0008)自由列表元素26F7F670的大小不正确(已死亡)
(试图记录如何查找内存错误的笔记)
首先安装Windbg:
http://www.microsoft.com/whdc/Devtools/Debugging/default.mspx
然后按照以下步骤打开pageheap:
gflags.exe /p /enable yourexecutable.exe /full
这将在每个堆分配后插入一个不可写页面。
之后从windbg内部启动可执行文件,任何堆外的写操作现在都将被该调试器捕获。要关闭pageheap,请使用以下命令:
gflags.exe /p /disable yourexecutable.exe
点击此处获取如何使用pageheap的更多信息。
针对 Windows 10 操作系统,你可以通过 GFlags 工具中的 PageHeap 选项 进行启用。该工具是作为 Windows 调试工具集 的一部分进行提供。
GFlags 中的 Page Heap 选项使你可以选择标准堆验证或完整页面堆验证。需要注意的是,完整堆验证会为每个分配使用一个完整的内存页,因此可能会导致系统内存短缺。
要在 GFlags 中启用 Page Heap:
• 启用 标准页堆验证,标准版本将在每个堆分配的末尾写入一个模式,并在释放分配时检查该模式。
要验证所有进程,请使用以下命令:
gflags /r +hpa
gflags /k +hpa
要验证单个进程,请使用以下命令:
gflags /p /enable ImageFileName
• 启用一个进程的 完整页面堆验证,此选项在每个分配的末尾放置一个不可访问的页面,以便程序如果尝试访问超出分配范围的内存时会立即停止运行。 由于内存消耗较大,因此应只在单个进程上使用该选项。
gflags /i ImageFileName +hpa
gflags /p /enable ImageFileName /full
上述两个命令可以互换使用。
注意:上述所有页堆设置都是全局设置,存储在注册表中(除了 /k)并保持有效,直到你更改它们。 /k 设置是内核标志设置,仅在此会话中生效,当 Windows 关闭时将丢失此设置。
另一个有用的工具是Application Verifier,但它不是 Windows 调试工具的一部分,而是包含在Windows 软件开发工具包 (SDK)中。
您可以在写入内存地址时设置断点。调试器将显示写入位置的代码,但您仍然需要确定哪些写入导致了问题。
更多关于Gflags和PageHeap的信息(它们非常有用):http://msdn.microsoft.com/en-us/library/windows/hardware/ff549561%28v=vs.85%29.aspx
如果您的代码能使用gcc编译并在Linux上运行,那么您可以使用valgrind来找到问题的源头(我不记得具体的标志,但我曾经成功地使用过一次)。
我假定使用C++语言。
如果错误是可复现的并且损坏的地址始终相同,您可以设置数据断点以在写入该地址时停止程序。
有一种方法可以解决问题,但我不建议使用。如果由于某些原因您仍然需要在不同的模式下构建,则此解决方法将允许从同一共享堆中分配和释放所有内存。API GetProcessHeap将允许您在不同的模块中访问共享堆。通过使用HeapAlloc和HeapFree,您可以在共享堆中分配和释放内存。注意:HeapAlloc和HeapFree应替换应用程序中所有对malloc和free的调用。
它救了我的命,我正在调试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的启动时间比以前长得多,这对于调试目的来说并不是问题。