-5
  1. 错误中的代码

    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;
    }
    
  2. 从 Visual Studio 2010 的项目菜单中确保构建为“Release”和“x64”(机器为 x64)

  3. 启用整页堆

    gflags /p /enable test.exe /full
    
  4. 使windbg默认调试器

    E:\installed\Debugging Tools for Windows (x64)>windbg -I
    
  5. cmd在没有调试器的情况下将代码作为单独的 exe 运行

    输出:

    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    

    之后,windbg 被发现腐败。而且我认为整页堆应该可以立即捕获损坏。

    关于为什么整页堆很烂的任何评论?

4

2 回答 2

31

由于堆分配需要对齐,因此在发生溢出时无法捕获未跨越对齐边界的溢出,因为内存保护是页粒度的,而不是字节粒度的。这是硬件限制。当您释放内存并检查尾字节是否被篡改时,将检测到溢出。

(顺便说一句,说某事很糟糕,会让你指责的那个人不太可能费心帮助你解决问题。只是一个小费。)

于 2012-11-09T18:49:12.567 回答
6

扩展雷蒙德的回应。如果您在调试器中查看通过 malloc 返回的原始指针,您将看到它距页面末尾 16 个字节。这是因为 x64 上的 HeapAlloc 对齐要求是 16 字节。因此,它将您要求的 1 个字节尽可能靠近页面的末尾。一旦你离开页面的末尾,你就会出错。

于 2012-11-09T18:58:59.847 回答