Search code examples
c++winapimemory-mapped-files

FILE_FLAG_DELETE_ON_CLOSE and memory mapped files


Not that it's particularly useful, but I'm curious as to why the following works, is it simply because the page still happens to be in memory even after the file is deleted? In which case, if the page is swapped out the data will be lost?

#include <iostream>
#include <memory>
#include <windows.h>

int main()
{
    typedef std::unique_ptr<void, decltype(&CloseHandle)> Handle;
    typedef std::unique_ptr<void, decltype(&UnmapViewOfFile)> View;

    View v(nullptr, UnmapViewOfFile);

    {
        Handle h(CreateFile(
            L"test",
            GENERIC_READ | GENERIC_WRITE,
            0,
            nullptr,
            CREATE_ALWAYS,
            FILE_FLAG_DELETE_ON_CLOSE,
            nullptr
        ), CloseHandle);

        // write something so CreateFileMapping succeeds
        DWORD sz;
        WriteFile(h.get(), "hello world", 12, &sz, nullptr);

        Handle m(CreateFileMapping(
            h.get(),
            nullptr,
            PAGE_READWRITE,
            0, 0,
            nullptr
        ), CloseHandle);

        v.reset(MapViewOfFile(
            m.get(),
            FILE_MAP_WRITE,
            0, 0,
            0
        ));

        char c;
        std::cin >> c; // File is still in folder
    }

    char c;
    std::cin >> c; // No file!

    std::cout << static_cast<char*>(v.get()); // Still writes
}

Solution

  • FILE_FLAG_DELETE_ON_CLOSE follows the unfortunate Windows tradition of referring to an unlink operation as "delete". In fact, the flag only causes the file to be unlinked from the specified directory when the file is closed.

    Like other operating systems, Windows only gives ordinary user code the ability to unlink a file from a particular directory. Deleting is always the operating system's decision, taking place when the file can no longer be referenced in any way.

    If you look, you'll see the file has in fact been unlinked from the directory, but it will not actually be deleted (and the space the data takes on disk available for re-use) until its reference count drops to zero. The mapping holds a reference.