内存映射文件的奇怪行为,一些观察和一些问题

发布于 2024-10-24 17:40:57 字数 946 浏览 6 评论 0原文

请看下面这段代码。

#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。任何解释其内部原理的有用链接都会很有帮助。

谢谢

Please look at this code below.

#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);
}

I have allocated only 32 bytes yet when I attempt to write past the allocated size, I don't get any error at all. Is this by design or is this a bug in Windows code? However, if you include the commented part, it gives error, as expected.

I ask this because I am thinking of using this "feature" to my advantage. Can I? FYI, I have Win XP ver 2002 SP 3 but I suspect this to be "fixed" in newer Windows' which might fail my code, IDK. Any useful link explaining some internals of this would really help.

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

季末如歌 2024-10-31 17:40:57

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

This isn't any different then writing past the end of a buffer that's allocated on the heap. The operating system can only slap your fingers if you write to virtual memory that isn't mapped. Mapping is page based, one page is 4096 bytes. You'll have to write past this page to get the kaboom. Change your for-loop to end at (4096+4)/4 to repro it.

人间不值得 2024-10-31 17:40:57

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

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

The virtual memory manager has to map memory by the page, so the extent will in effect be rounded up to the nearest 4kB (or whatever your system page size is).

I don't think it's documented whether writes into the same page as mapped data, but beyond the end of the mapping, will be committed back to the file. So don't rely on that behavior, it could easily change between Windows versions.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文