2

在我们的应用程序中,我们必须能够将多个(即最多 4 个)文件映射到内存中(通过mapViewOfFile)。很长一段时间以来,这都不是问题,但是随着过去几年文件越来越大,现在内存碎片阻止了我们映射那些大文件(文件大约 200 MB)。如果此时没有加载其他文件,则问题可能已经存在。

我现在正在寻找一种方法来确保映射始终成功。因此,我想在程序开始时只为映射保留一块内存,因此碎片的影响要小得多。

我的第一种方法是HeapCreate一个私有堆,然后我会HeapAlloc一块足够大的内存来保存一个文件的映射,然后使用MapViewOfFileEx和该块的地址。当然,地址必须与内存分配粒度相匹配。但映射仍然失败,错误代码为 ERROR_INVALID_ADDRESS (487)。

接下来我用VirtualAloc尝试了同样的事情。我的理解是,当我传递参数 MEM_RESERVE 时,我就可以将该内存用于我想要的任何东西,例如映射文件视图。但我发现这是不可能的(与上面相同的错误代码),直到我再次用VirtualFree完全释放整个块。因此,将不再为下一个文件保留内存。

我已经在使用低碎片堆功能,它对我们几乎没有用处。重写我们的代码以仅使用文件的较小视图目前不是一种选择。我还看了这篇文章Can address space becycled for multiple calls to MapViewOfFileEx without chance? 但没有发现它非常有用,并希望有另一种可能性。

你有什么建议我可以做什么或我的设计可能有问题吗?谢谢你。

4

1 回答 1

0

好吧,文档MapViewOfFileEx很清楚:“建议的地址用于指定文件应在多个进程中映射到同一地址。这要求地址空间区域在所有涉及的进程中都可用。没有其他内存分配可以发生在用于映射的区域,包括使用VirtualAlloc

低碎片堆旨在防止即使相对较小的分配失败。即它避免了 1 个字节的空洞,因此 2 个字节的分配将保持更长时间。按照 32 位标准,您的分配并不小。

实际上,这会受到伤害。如果您真的需要它,请重新实现内存映射文件。所有必要的功能都可用。使用向量异常处理程序在源中分页,并用于QueryWorkingSet确定页面是否脏。

于 2012-04-24T22:08:17.633 回答