【问题标题】:C++ MapViewOfFile failsC++ MapViewOfFile 失败
【发布时间】:2013-09-25 22:54:01
【问题描述】:

我正在尝试使用 VS2010 在 Windows 上对文件进行内存映射。 我在 DLL 中执行此操作。 DLL 的第一个实例可以很好地映射文件。 同一进程内的第二个实例导致

*ppvData = ::MapViewOfFile( *phMapping, FILE_MAP_READ, 0, 0, 0 );

失败并显示错误“没有足够的内存可用于此命令”。 我不确定为什么会这样。

如果我映射 2 个不同的文件而不是两次相同的文件,一切正常,所以我不相信“内存不足”错误消息。

谢谢。

hr = MapFile(sPath, &m_hVoiceData, &m_pVoiceData,wsErr );

HRESULT CTTSEngObj::MapFile( wstring uPath,  // Value that contains file path
                            HANDLE * phMapping,          // Pointer to file mapping handle
                            void ** ppvData,             // Pointer to the data
                            wstring &uError)
{
    HRESULT hr = S_OK;
    CSpDynamicString dstrFilePath(uPath.c_str());

    if ( SUCCEEDED( hr ) )
    {
        bool fWorked = false;
        *phMapping = NULL;
        *ppvData = NULL;
        HANDLE hFile;
#ifdef _WIN32_WCE
        hFile = CreateFileForMapping( dstrFilePath, GENERIC_READ,
                                      FILE_SHARE_READ, NULL, OPEN_EXISTING,
                                      FILE_ATTRIBUTE_NORMAL, NULL );
#else
        hFile = CreateFile(CW2T(dstrFilePath), GENERIC_READ,
                            FILE_SHARE_READ, NULL, OPEN_EXISTING,
                            FILE_ATTRIBUTE_NORMAL, NULL );
#endif
        if (hFile != INVALID_HANDLE_VALUE)
        {
            *phMapping = ::CreateFileMapping( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
            if (*phMapping)
            {
                *ppvData = ::MapViewOfFile( *phMapping, FILE_MAP_READ, 0, 0, 0 );
                if (*ppvData)
                {
                    fWorked = true;
                }
                else
                {
                    uError=GetLastErrorStdStrW();
                }
            }
            else
            {
                uError=L"mapfile: fm failed";
            }
            ::CloseHandle( hFile );
        }
        else
        {
            uError=L"mapfile: invalidhandle";
        }
        if (!fWorked)
        {
            hr = HRESULT_FROM_WIN32(::GetLastError());
            if (*phMapping)
            {
                ::CloseHandle(*phMapping);
                *phMapping = NULL;
            }
        }
    }
    else
    {
        uError=L"mapfile: dynstr";
    }
    return hr;
} /* CTTSEngObj::MapFile */

这就是它的声明方式:

class ATL_NO_VTABLE CTTSEngObj : 
    public CComObjectRootEx<CComMultiThreadModel>,
    public CComCoClass<CTTSEngObj, &CLSID_SampleTTSEngine>,
    public ISpTTSEngine,
    public ISpObjectWithToken
{

  private:
    CComPtr<ISpObjectToken> m_cpToken;
    HANDLE                  m_hVoiceData;
    void*                   m_pVoiceData;

【问题讨论】:

  • 你看the documentation了吗?就像几乎所有其他 Win32 调用一样,“如果函数失败,则返回值为 NULL。要获取扩展的错误信息,请调用 GetLastError。”
  • 完成并编辑了我的帖子。
  • 您应该在函数失败后立即保存错误代码,因为其他 API 调用(例如您对 CloseHandle 的调用)可能会修改该值。
  • *phMapping = 之类的东西在我看来很可疑。 AFAICT 他们会尝试写入地址 0。声明它们不带类型标识符也是一个坏主意:默认类型是 int 而 HANDLE 通常是 PVOID - 地址算术不同。
  • “不信任”Windows 是没有意义的,它不仅会因为日子不好过而产生错误。简单的解释是 Windows 告诉您的,文件太大,无法容纳虚拟内存地址空间中的可用漏洞。这就是 MapViewOfFile() 有 dwNumberOfBytesToMap 参数的原因。

标签: c++ windows memory-mapped-files


【解决方案1】:

您请求将整个文件映射到内存中。它有多大?很可能没有足够大的连续范围的未分配进程的地址空间。

【讨论】:

  • 问题是,如果我从不同的进程中执行相同的操作,它会起作用。
  • “不同的进程”有不同的虚拟地址空间。
  • 文件大小为 200 mb。
  • 考虑到可能的地址空间碎片和其他可能的限制,它已经足够大了。您可以尝试映射文件的一部分来检查这一点。
  • 但是......如果我使用 2 个不同的进程,它是否也不起作用?
猜你喜欢
  • 1970-01-01
  • 2013-04-08
  • 2015-06-15
  • 2011-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多