1

我在这里处理了一个有点奇怪的场景,但这正是我计划创建的。它只是一种特殊的测试软件......

我的环境:MSVS 2012,Windows 7/8 32b/64b。

所以,首先我正在创建一些内部结构/缓冲区/等以在我的应用程序中使用,然后我正在做这样的事情(这里简化了一点,请把它当作伪代码对待):

{
   std::deque<boost::scoped_array<unsigned char>> deque;
   try {
     while (1) {
       deque.push_back(boost::scoped_array<unsigned char>(new unsigned char[system_page_size])); // happens to be 4096 on my system
     }
   }
   catch (std::bad_alloc& ex) { ... }
   // do something here
}

我需要使用尽可能多的内存。我一次分配整个页面(也许这很糟糕,应该为双端队列/智能 ptr 的数据留出一些空间?)。当 CRT 决定不能再分配时,我会做更多的事情(根本不依赖任何内存可用性),然后退出范围。它将触发析构函数链,所有这些数据都应该被释放。

这很好用。但我碰巧在一个循环中进入这个奇怪的范围不是一次而是 10 次。它有时会工作 2 或 3 次。有时只有一次。下次我只会得到内存不足的错误,就是这样。

从我的角度来看,我需要重新启动整个过程才能真正强制释放内存。有没有一种方法可以在单个过程中实现这一目标?

我可以考虑尝试不同的分配器——也许是 CRT 问题?我也玩了一点堆操作(即低碎片堆),但也没有帮助。

4

2 回答 2

0

为什么不使用 MEM_RESERVE通过几个大型VirtualAlloc调用来保留进程的整个内存空间。然后,您稍后将在每个内存范围上调用 VirtualFree 以释放。这仍然需要一些堆分配,就像您在这里所做的那样,以耗尽当前堆的其余部分。它会更快并消除您必须经历的页面文件流失。

至于你的具体问题,不知道你为什么会遇到。保留所有内存以使堆无法扩展应该有助于减少不确定性。

于 2012-12-28T23:17:49.083 回答
0

如果您使用大量内存,请使用某种平板分配(VirtualAlloc 将为您提供内存),然后,原则上[假设您在该块中创建的对象不需要析构函数做某事] ,您可以一次性扔掉整个块,而不是使用无数次删除 - 额外的好处是节省时间并保证您的内存已完全释放。

我怀疑您可能遇到问题的一个原因是必须先清除已释放的块,然后才能回收它们。这是在内核的后台线程中完成的。当然,使用 VirtualALloc 实际上对这个帐户没有帮助。

当然,您也可能会出现内存碎片,在这种情况下,使用旨在避免这种情况的磁头会起作用。

于 2012-12-28T23:29:01.687 回答