是否有一个新的等待直到内存可用?

时间:2013-12-03 06:22:38

标签: c++ exception-handling bad-alloc

在阅读this question之前,我从未认真对待异常处理。现在我看到了必要性,但仍然觉得“编写异常安全代码非常困难”。

在该问题的接受答案中查看此示例:

void doSomething(T & t)
{
   if(std::numeric_limits<int>::max() > t.integer)  // 1.   nothrow/nofail
      t.integer += 1 ;                              // 1'.  nothrow/nofail
   X * x = new X() ;                // 2. basic : can throw with new and X constructor
   t.list.push_back(x) ;            // 3. strong : can throw
   x->doSomethingThatCanThrow() ;   // 4. basic : can throw
}

正如答案所说,我可以使用std::unique_ptr轻松提供基本保证。但是当我抓到std::bad_alloc时,我不知道它是否发生在push_backx->doSomethingThatCanThrow()中,所以我不知道t.list是否仍然“好”或者它最后一个元素没有完全准备好。然后唯一的选择是丢弃t,显示可怕的消息并中止,如果t对整个程序是必不可少的。

具有强保证的代码没有问题,但“它可能变得昂贵”(此示例涉及大型列表的副本),并且不那么可读。

可能的解决方案可能是让new等待内存可用,删除最烦人的异常std::bad_alloc。然后2.和3.不会抛出(提供X的构造和复制总是成功)。我可以在try块中包装4.并在这里处理异常(和pop_back列表)。然后该函数将提供nothrow保证,列表将始终包含好东西。

用户不会关心100%CPU和100%RAM之间的区别。当他们看到程序挂起时,他们将关闭其他程序,以便new找到足够的内存并继续。

我的问题:这可以实施吗?是否有一个新的等待直到内存可用?我可以全局应用它(例如通过#define new ...),因此在C ++标准化之前的库可以在临时的100%RAM中存活吗?

1 个答案:

答案 0 :(得分:2)

这是一个有问题的设计,但你肯定可以用'new-handler'来做到这一点。默认的新处理程序只会抛出std::bad_alloc。如果new-handler返回,new将循环,并尝试再次分配。 nothrow new运算符也使用它,但是捕获了new-handler抛出的std::bad_alloc,并返回NULL

您只需要set自定义void (*)()处理函数的新处理程序。至少,你可能想让这个过程暂停一段时间 - 比如1/10秒。同样,程序可能无法继续 - 例如,Linux具有可以由管理员配置的“OOM杀手”。