1

gflags 配置为仅启用“启用堆尾检查”。未启用 PageHeap。

c:\Program Files (x86)\Windows Kits\10\Debuggers\x64>gflags /i test.exe
Current Registry Settings for test.exe executable are: 00000010
    htc - Enable heap tail checking

在下面的程序中,在使用 16 字节对齐的堆外分配了一个 4 字节整数。所以剩下的 12 个字节用标记字节填充。

int main()
{
    int *p = new int{};

    for (size_t i = 0; i < 16; ++i)
    {
        ((char*)p)[i] = '0';
        cout << ((char*)p)[i] << endl;
    }
    delete p;
    cout << "After delete\n";
    return 0;
}

根据 MSFT,这非常简单。

此标志在每个分配的末尾添加一个短模式。Windows 堆管理器在块被释放时检测到模式,如果块被修改,堆管理器会进入调试器。

然而,这并没有发生。未捕获缓冲区溢出,并且该过程成功完成。

循环前的内存布局,从分配的整数地址开始。ab ab ..其余 12 个字节用正确的特定字节模式填充。

在此处输入图像描述

这是在循环执行之后。12 字节模式已超出。 在此处输入图像描述

这是在内存块被释放之后。 在此处输入图像描述

没有例外,没有调试器启动。之后的消息delete也打印成功了。 在此处输入图像描述

注意: 如果我同时启用了 PageHeap ,那么同样的尾部缓冲区溢出问题(我确信它当然没有溢出到受 PageHeap 保护的下一页)就会被捕获。

这是堆管理器中的错误吗?我认为“启用堆尾检查”和 PageHeap 是两个独立的功能。

4

0 回答 0