Windows上MapViewOfFile的引用计数问题

看来MapViewOfFile增加了文件映射内核对象的引用计数。

MapViewOfFile的MSDN描述引用:

文件映射对象的映射视图维护对该对象的内部引用,并且一个文件映射对象不会closures,直到释放所有引用为止。 因此,要完全closures文件映射对象,应用程序必须通过调用UnmapViewOfFile来取消映射文件映射对象的所有映射视图,并通过调用CloseHandleclosures文件映射对象CloseHandle 。 这些function可以按任何顺序调用。

另外,从Windows通过C / C ++,第5版

上面的代码显示了操作内存映射文件的“预期”方法。 但是,它没有显示的是,当您调用MapViewOfFile时,系统递增文件对象和文件映射对象的使用计数…

尽pipe如此,我的实际testing却暗示相反的情况。 我在Windows 10 64位上使用Visual Studio 2015。 testing程序如下:

 #include <windows.h> int main() { HANDLE h = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 128, "test"); void* p_memory = MapViewOfFile(h, FILE_MAP_WRITE, 0, 0, 0); CloseHandle(h); h = OpenFileMappingA(FILE_MAP_WRITE, FALSE, "test"); DWORD dw = GetLastError(); // ERROR_FILE_NOT_FOUND } 

OpenFileMapping调用失败,最后一个错误ERROR_FILE_NOT_FOUND 。 当我删除CloseHandle调用时,一切都会好起来的。 这意味着CloseHandle调用消除了文件映射内核对象的最后引用计数并将其销毁。 这又意味着MapViewOfFile实际上不增加对象的引用计数。

我想确定发生了什么事情,以及MapViewOfFile关于文件映射内核对象的引用计数的确切语义是什么。

通过使用文件作为后备存储而不是分页文件,可以使其更具说服力:

 int main() { const char* path = "mmf.bin"; DeleteFile(path); HANDLE hFile = CreateFile(path, GENERIC_READ | GENERIC_WRITE, FILE_FLAG_DELETE_ON_CLOSE, NULL, CREATE_NEW, 0, NULL); HANDLE h = CreateFileMappingA(hFile, NULL, PAGE_READWRITE, 0, 128, "test"); int* p_memory = (int*)MapViewOfFile(h, FILE_MAP_WRITE, 0, 0, 128); CloseHandle(h); DWORD attr = GetFileAttributes(path); if (attr != INVALID_FILE_ATTRIBUTES) puts("File still exists"); else puts("File is gone"); } 

输出:文件不见了

所以“系统递增文件对象的使用次数”是绝对不正确的。 而且我认为你反驳说它增加了文件映射对象上的使用计数。 不知道该怎么做,里奇特经常不会弄错。 这本书的勘误也没有。 它可能在Windows的早期版本中以这种方式工作,不确定,因为我从来没有故意错误。 我们将不得不坚持SDK文档实际所说的内容:

共享文件映射对象不会被销毁,直到所有使用它的进程都通过CloseHandle函数关闭它们的句柄。