gpt4 book ai didi

c++ - 如何处理 C++ 中的 bad_alloc?

转载 作者:IT老高 更新时间:2023-10-28 13:57:45 25 4
gpt4 key购买 nike

有一个名为 foo 的方法有时会返回以下错误:

terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Abort

有没有办法可以使用 try-catch block 来阻止此错误终止我的程序(我要做的就是返回 - 1)?

如果有,它的语法是什么?

我还能如何处理 C++ 中的 bad_alloc

最佳答案

一般情况下,您不能,并且不应尝试来响应此错误。 bad_alloc 表示无法分配资源,因为没有足够的可用内存。在大多数情况下,您的程序无法应对这种情况,而尽快终止是唯一有意义的行为。

更糟糕的是,现代操作系统经常过度分配:在这样的系统上,mallocnew 可以返回一个有效的指针,即使没有足够的可用内存 - std::bad_alloc 永远不会被抛出,或者至少不是内存耗尽的可靠迹象。相反,尝试访问分配的内存将导致无法捕获的段错误(您可以处理段错误信号,但之后您无法恢复程序)。

在捕获 std::bad_alloc 时,您唯一能做的就是记录错误,并尝试通过释放未完成的资源来确保安全的程序终止(但这在正常情况下会自动完成)如果程序正确使用 RAII,则在引发错误后展开堆栈的过程。

在某些情况下,程序可能会尝试释放一些内存并重试,或者使用辅助内存(= 磁盘)而不是 RAM,但这些机会仅存在于具有严格条件的特定场景中:

  1. The application must ensure that it runs on a system that does not overcommit memory ,即它在分配时发出失败的信号,而不是稍后。
  2. 应用程序必须能够立即释放内存,同时不会有任何进一步的意外分配。

应用程序控制第 1 点的情况极为罕见——用户空间应用程序从不这样做,这是一个系统范围的设置,需要 root 权限才能更改。1

好的,假设您已经确定了第 1 点。例如,您现在可以使用 LRU cache对于您的一些数据(可能是一些可以按需重新生成或重新加载的特别大的业务对象)。接下来,您需要将可能失败的实际逻辑放入支持重试的函数中——换句话说,如果它被中止,您可以重新启动它:

lru_cache<widget> widget_cache;

double perform_operation(int widget_id) {
std::optional<widget> maybe_widget = widget_cache.find_by_id(widget_id);
if (not maybe_widget) {
maybe_widget = widget_cache.store(widget_id, load_widget_from_disk(widget_id));
}
return maybe_widget->frobnicate();
}



for (int num_attempts = 0; num_attempts < MAX_NUM_ATTEMPTS; ++num_attempts) {
try {
return perform_operation(widget_id);
} catch (std::bad_alloc const&) {
if (widget_cache.empty()) throw; // memory error elsewhere.
widget_cache.remove_oldest();
}
}

// Handle too many failed attempts here.

但即使在这里,使用 std::set_new_handler 而不是处理 std::bad_alloc 提供了相同的好处并且会更简单。


1 如果您正在创建一个确实控制点 1 的应用程序,并且您正在阅读此答案,请给我发一封电子邮件,我真的很好奇关于你的情况。

关于c++ - 如何处理 C++ 中的 bad_alloc?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9456728/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com