错误中的代码
int main() { void *ptr = 0; int overrun = 1; ptr = malloc(overrun); while(overrun++) { if(!ptr) while(1) Sleep(500); *((char*)ptr + (overrun+1)) = 'a'; printf("\n%d\n",overrun); } return 0; }
从 Visual Studio 2010 的项目菜单中确保构建为“Release”和“x64”(机器为 x64)
启用整页堆
gflags /p /enable test.exe /full
使windbg默认调试器
E:\installed\Debugging Tools for Windows (x64)>windbg -I
cmd
在没有调试器的情况下将代码作为单独的 exe 运行输出:
2 3 4 5 6 7 8 9 10 11 12 13 14
之后,windbg 被发现腐败。而且我认为整页堆应该可以立即捕获损坏。
关于为什么整页堆很烂的任何评论?
user1813004
问问题
1156 次
2 回答
31
由于堆分配需要对齐,因此在发生溢出时无法捕获未跨越对齐边界的溢出,因为内存保护是页粒度的,而不是字节粒度的。这是硬件限制。当您释放内存并检查尾字节是否被篡改时,将检测到溢出。
(顺便说一句,说某事很糟糕,会让你指责的那个人不太可能费心帮助你解决问题。只是一个小费。)
于 2012-11-09T18:49:12.567 回答
6
扩展雷蒙德的回应。如果您在调试器中查看通过 malloc 返回的原始指针,您将看到它距页面末尾 16 个字节。这是因为 x64 上的 HeapAlloc 对齐要求是 16 字节。因此,它将您要求的 1 个字节尽可能靠近页面的末尾。一旦你离开页面的末尾,你就会出错。
于 2012-11-09T18:58:59.847 回答