【发布时间】:2012-09-25 07:11:39
【问题描述】:
我睡不着! :)
我在 Windows 上有一个相当大的项目,但遇到了一些堆损坏问题。我已经阅读了所有 SO,包括这个不错的主题:How to debug heap corruption errors?,但是没有什么适合开箱即用的帮助我。 Debug CRT 和 BoundsChecker 检测到堆损坏,但地址总是不同的,检测点总是远离实际的内存覆盖。我一直到半夜都没睡,并制作了以下 hack:
DWORD PageSize = 0;
inline void SetPageSize()
{
if ( !PageSize )
{
SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo);
PageSize = sysInfo.dwPageSize;
}
}
void* operator new (size_t nSize)
{
SetPageSize();
size_t Extra = nSize % PageSize;
nSize = nSize + ( PageSize - Extra );
return Ptr = VirtualAlloc( 0, nSize, MEM_COMMIT, PAGE_READWRITE);
}
void operator delete (void* pPtr)
{
MEMORY_BASIC_INFORMATION mbi;
VirtualQuery(pPtr, &mbi, sizeof(mbi));
// leave pages in reserved state, but free the physical memory
VirtualFree(pPtr, 0, MEM_DECOMMIT);
DWORD OldProtect;
// protect the address space, so noone can access those pages
VirtualProtect(pPtr, mbi.RegionSize, PAGE_NOACCESS, &OldProtect);
}
一些堆损坏错误变得很明显,我能够修复它们。退出时不再有 Debug CRT 警告。但是,我对这个 hack 有一些疑问:
1.它会产生任何误报吗?
2. 它会漏掉一些堆损坏吗? (即使我们替换 malloc/realloc/free?)
3. 使用OUT_OF_MEMORY 无法在 32 位上运行,只能在 64 位上运行。我说得对吗,我们只是用完了 32 位的虚拟地址空间?
【问题讨论】:
-
您是否想重新发明PageHeap GFLAG?见Detecting Heap Corruption Using GFlags and Dumps
-
@Remus Rusanu:链接!我很想在 24 小时前拥有它 :)
-
下次你就知道了:)
-
虽然它会捕获重用后释放错误,但请注意分配任何类型的对象(例如,4 字节大小)将从您的地址空间中占用 64kiB,因为这是最小分配Windows 将执行的粒度。这也是它在 OUT_OF_MEMORY 低于 32 位时失败的原因——这是最糟糕的事情。
标签: c++ c heap-memory heap-corruption virtualalloc