【发布时间】:2023-04-06 08:49:02
【问题描述】:
在我们的应用程序中,我们必须能够将多个(即最多 4 个)文件映射到内存中(通过 mapViewOfFile)。很长一段时间以来,这都不是问题,但是随着过去几年文件越来越大,现在内存碎片阻止了我们映射那些大文件(文件大约 200 MB)。如果此时没有加载其他文件,则问题可能已经存在。
我现在正在寻找一种方法来确保映射始终成功。因此,我想在程序启动时只为映射保留一块内存,因此碎片受到的影响要小得多。
我的第一种方法是 HeapCreate 一个私有堆,然后我将 HeapAlloc 一块足够大的内存来保存一个文件的映射,然后使用 MapViewOfFileEx 与该块的地址。当然,地址必须与内存分配粒度相匹配。但映射仍然失败,错误代码为 ERROR_INVALID_ADDRESS (487)。
接下来我用 VirtualAloc 尝试了同样的事情。我的理解是,当我传递参数 MEM_RESERVE 时,我就可以将该内存用于我想要的任何东西,例如映射文件的视图。但我发现这是不可能的(与上面相同的错误代码),直到我再次使用 VirtualFree 完全释放整个块。因此,将不再为下一个文件保留内存。
我已经在使用 低碎片堆 功能,它对我们几乎没有用处。重写我们的代码以仅使用文件的较小视图目前不是一种选择。我也看了这篇 Can address space be recycled for multiple calls to MapViewOfFileEx without chance of failure? 的帖子,但没有发现它很有用,并希望有其他的可能性。
您对我能做什么或我的设计可能有什么问题有什么建议吗? 谢谢。
【问题讨论】:
-
目前最简单的解决方案是使用 64 位寻址。
-
@MSalters 这肯定会有所帮助,但与只需要编写一些新函数来正确分配内存的解决方案相比,这意味着更多的工作。加上我们的客户都使用 32 位。不过还是谢谢。
-
MMF 在 Windows 中被过度使用。它已经通过文件系统缓存对文件进行了非常好的内存映射视图。我不知道你的使用模式,但做尝试只使用 ReadFile/SetFilePointer 看看你是否真的减速了。
-
@HansPassant atm 每段代码都有自己的指向映射的指针,指向对应对象的位置。这些指针就是这样使用的:指向一些内存的指针。所以必须先写一些访问api。但话又说回来,我可能不得不这样做。
-
那么这些指针就像是整个文件映射的小视图?问题解决了。
标签: c++ windows-xp