2

请看下面的这段代码。

#include <windows.h>

void Write(char *pBuffer)
{
//  pBuffer -= 4*sizeof(int);
    for(int i = 0; i<20; i++)
        *(pBuffer + sizeof(int)*i) = i+1;
}

void main()
{
    HANDLE hFile = ::CreateFile("file", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

    if(INVALID_HANDLE_VALUE == hFile)
    {
        ::MessageBox(NULL, "", "Error", 0);
        return;
    }

    HANDLE hMMF = ::CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 32, NULL);

    char *pBuffer = (char*)::MapViewOfFile(hMMF, FILE_MAP_WRITE, 0, 0, 0);

    Write(pBuffer);

    ::FlushViewOfFile(pBuffer, 100);

    ::UnmapViewOfFile(pBuffer);
}

我只分配了 32 个字节,但是当我尝试写入超过分配的大小时,我根本没有收到任何错误。这是设计使然还是 Windows 代码中的错误?但是,如果您包含注释部分,则会按预期给出错误。

我问这个是因为我正在考虑利用这个“功能”来发挥我的优势。我可以吗?仅供参考,我有 Win XP ver 2002 SP 3,但我怀疑这在较新的 Windows 中已“修复”,这可能会使我的代码 IDK 失败。任何有用的链接解释这其中的一些内部都会有帮助。

谢谢

4

2 回答 2

2

这与写入在堆上分配的缓冲区的末尾没有任何不同。如果您写入未映射的虚拟内存,操作系统只能拍打您的手指。映射是基于页面的,一页是 4096 字节。你必须写过去这个页面才能得到kaboom。将您的 for 循环更改为在 (4096+4)/4 处结束以重现它。

于 2011-03-20T18:29:20.630 回答
0

虚拟内存管理器必须按页面映射内存,因此范围实际上将四舍五入到最接近的 4kB(或任何您的系统页面大小)。

我认为没有记录是否写入与映射数据相同的页面,但在映射结束之后,是否将提交回文件。所以不要依赖这种行为,它很容易在 Windows 版本之间改变。

于 2011-03-20T18:28:42.757 回答