【问题标题】:Why does MapViewOfFile fail with ERROR_ACCESS_DENIED?为什么 MapViewOfFile 会因 ERROR_ACCESS_DENIED 而失败?
【发布时间】:2013-04-08 06:44:35
【问题描述】:

我在 WinAPI 的 MapViewOfFile 函数中遇到了这种情况。互联网搜索没有发现任何明显的修复,所以我将在这里分享我的问题和解决方案。

考虑以下 sn-p:

const char *name = "Global\\Object_Name";
unsigned long size = get_object_size();

HANDLE handle = CreateFileMapping(INVALID_HANDLE_VALUE,
                                  NULL,
                                  PAGE_READWRITE,
                                  0,
                                  size,
                                  name);

if (!handle || handle == INVALID_HANDLE_VALUE)
    exit(GetLastError());

bool created = GetLastError() == 0;

void *block = MapViewOfFile( handle,
                             FILE_MAP_ALL_ACCESS,
                             0,
                             0,
                             size);

if (block == NULL)
    exit(GetLastError());

在一种特殊情况下,CreateFileMapping 成功返回了句柄。 GetLastError 正在返回 ERROR_ALREADY_EXISTS,所以 created == false。现在,对MapViewOfFile 的调用,使用我传递给CreateFileMapping 的相同大小,返回NULLGetLastError 返回0x05ERROR_ACCESS_DENIED。该进程以管理员权限运行。

MSDN 文档并没有真正提到会发生这种情况的任何原因。那么为什么CreateFileMapping 成功,而MapViewOfFile 失败呢?

【问题讨论】:

    标签: c winapi shared-memory


    【解决方案1】:

    我确信有很多原因会导致调用 MapViewOfFile 时出现 ERROR_ACCESS_DENIED。在我的特殊情况下,这是由于 size 参数。

    提示是created == false。它表明对象"Global\\Object_Name" 已经创建。无论出于何种原因,创建调用都会以较小的大小初始化该部分。对于看似疏忽的情况,第二次调用 CreateFileMapping 会很高兴地为您提供已经存在的对象的句柄,即使您要求更大的映射。

    MapViewOfFile 的调用现在失败,因为它请求的视图大于实际部分。

    因此,如果您遇到第二次调用 MapViewOfFile 失败的类似情况,请检查您尝试映射到的大小。

    可能是第二个项目使用不同的结构对齐方式进行编译,导致 sizeof() 运算符确定不同的值,或者其他一些大小确定函数的行为未达到预期。

    【讨论】:

      【解决方案2】:

      经过一番苦恼,我终于在我的应用程序中找到了导致此错误的原因,以防其他人遇到同样的问题,问题不在于 MapViewOfFile 方法,而在于 CreateFileMapping,createFileMapping 的大小应该是文件的大小,而不是要读取的元素的大小,如果您不知道大小,那么它应该是 0,这不适用于 MapViewOfFile,因为要传递的值是 size 的长度阻止你想读/写。

      您的代码将如下所示:

      const char *name = "Global\\Object_Name";
      unsigned long size = get_object_size();
      
      HANDLE handle = CreateFileMapping(INVALID_HANDLE_VALUE,
                                        NULL,
                                        PAGE_READWRITE,
                                        0,
                                        0,
                                        name);
      
      if (!handle || handle == INVALID_HANDLE_VALUE)
          exit(GetLastError());
      
      bool created = GetLastError() == 0;
      
      void *block = MapViewOfFile( handle,
                                   FILE_MAP_ALL_ACCESS,
                                   0,
                                   0,
                                   size);
      
      if (block == NULL)
          exit(GetLastError());
      

      只是把它放在这里是为了记录我的发现,不幸的是,当你不知道是什么导致它时,很难搜索到这个错误。我希望这可以为其他人节省几个小时。

      【讨论】:

        猜你喜欢
        • 2011-07-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-30
        • 2020-10-14
        相关资源
        最近更新 更多