我有一个适用于Windows Mobile 6 ARMV4I的Visual Studio 2008 C ++项目,我正在使用内存映射文件。不幸的是,它导致设备锁定。我可以用这段代码来证明这个问题:
#include <list>
#include <algorithm>
int _tmain(int argc, _TCHAR* argv[])
{
DWORD alloc_size = 256;
DWORD alloc_max = 16 * 1024 * 1024;
DWORD alloc_count = alloc_max / alloc_size;
HANDLE f = ::CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, alloc_max, NULL );
std::list< void* > l;
for( DWORD i = 0; i < alloc_count; ++i )
{
// device freezes after 65529 iterations
l.push_back( ::MapViewOfFile( f, FILE_MAP_READ | FILE_MAP_WRITE, 0, i * alloc_size, alloc_size ) );
}
std::for_each( l.rbegin(), l.rend(), ::UnmapViewOfFile );
::CloseHandle( f );
return 0;
}
在我的测试中,经过65529次迭代后,Windows Mobile 6 Classic Emulator将冻结。这是我正在做错的事情还是我应该注意的平台问题?
谢谢, PaulH
编辑:增加到/ STACK:1048576,4096允许我在设备冻结之前达到65535次迭代。
Edit2:根据失败前的GlobalMemoryStatus
,设备有70.5MB / 94.1MB的可用物理内存。
Edit3 :我可以创建两个MMF并将它们加载到65500 * 256字节。但是,它们都不能单独超过65535次分配。实际上,alloc大小并不重要。我可以将它减半到128个字节,但我仍然在> 65535次迭代中失败。
Edit4:使用实际文件支持MMF似乎没有任何区别。失败> 65535次迭代。
答案 0 :(得分:0)
在Windows中,内存在页面中管理。此外,在分配这些页面时存在最小粒度。在桌面Windows上,页面通常为4KiB,最小粒度通常为64KiB。如果您尝试VirtualAlloc
或MapViewOfFile
的尺寸小于此值,它将被四舍五入,您将浪费一些RAM。
我非常确定Windows Mobile上的页面大小也是4KiB - 因此对于每个256字节MapViewOfFile
,它实际上必须保留至少 4KiB。您可以致电GetSystemInfo
为自己获取这些号码。
这意味着您的代码实际上保留至少 256MiB,如果分配粒度更高,则可能更多。您的应用正在耗尽其地址空间。
答案 1 :(得分:0)
根据this(参见图4),只有256MB的地址空间被分配用于内存映射文件。 64K分配* 4KB = 256MB,因此您达到了极限。
答案 2 :(得分:0)
我与有权访问来源的人进行了交谈。事实证明,MapViewOfFile
使用的内部参考计数器是USHORT
。因此,在65535次迭代中,它溢出并引起整个地方的仇恨和不满,最终停止了系统。
因此,存储器映射文件中存在未记录的65535个打开视图限制。
-PaulH