【发布时间】: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