初始化向量时检查错误分配

Posted

技术标签:

【中文标题】初始化向量时检查错误分配【英文标题】:Check for bad alloc when initializing a vector 【发布时间】:2018-05-03 14:01:01 【问题描述】:

由于我已经读过向量中的每个元素都是在堆上创建的,我想知道您是否需要检查堆上是否有足够的内存,或者如果没有足够的可用空间会发生什么?

例如,这样的事情甚至有必要吗?:

   try 
       std::vector<T> map;
       map.pushback(t);
     catch (const std::bad_alloc& e) 
        std::cout << "Allocation failed: " << e.what() << '\n';
    

【问题讨论】:

您并没有真正处理异常。假设操作成功,以下代码将继续执行。在不放弃您最终尝试执行的任何操作的情况下,很难处理std::bad_alloc。如果你想处理std::bad_alloc,你通常会希望远离故障点,在那里可以做一些有意义的事情。 【参考方案1】:

在大多数情况下,您将得到std::bad_alloc 抛出的场景是您尝试分配过多内存而系统无能为力的场景。在大多数情况下,这不是可恢复的错误。将整个程序包装在 try-catch 块中可能会发出错误消息 ("System ran out of memory!") 可能是有意义的,但在大多数情况下,不值得捕获此错误,因为不会有适合您的恢复选项程序。

但请注意,我在这里对冲我的语言。这完全取决于您使用的应用程序类型。例如,如果您正在编写一个根据可用内存量进行自我调整的程序(也许它会尝试分配 64GB 内存,但如果不能,那么它只会写入/读取临时文件?)它将这样的分配包装在 try-catch 块中并为内存分配失败的场景添加逻辑可能是合乎逻辑的。

当您花费更多时间编写代码时,您需要捕获此错误的场景与不需要捕获此错误的场景之间的差异会变得更加明显。

【讨论】:

【参考方案2】:

例如,这样的事情甚至有必要吗?:

如documentation中所述

如果抛出异常(可能是由于 Allocator::allocate() 或元素复制/移动构造函数/赋值),则此函数无效(强异常保证)。

所以push_back() 可以在重新分配发生时抛出这样的异常。如果您需要在每次调用时检查它真的取决于您的应用程序逻辑,所以除了您之外没有人可以告诉您是否有必要。

【讨论】:

【参考方案3】:

因为我已经读过向量中的每个元素都是在堆上创建的

std::vector 拥有一个堆分配的连续缓冲区。元素被添加到缓冲区。每个元素都不是单独分配的。

如果缓冲区已满,std::vector 会自动分配一个更大的新缓冲区并将每个元素从旧缓冲区移到新缓冲区。


例如,这样的事情甚至有必要吗?

这可能是矫枉过正,除非您期望 push_back 出于某种原因消耗所有可用内存。处理std::bad_alloc 在某些情况下可能很有用,但大多数情况下您不想从内存耗尽中恢复 - 这完全取决于您正在处理的程序类型。

您可能还想在 catch 块中做一些有意义的事情 - 打印不会解决问题。

【讨论】:

以上是关于初始化向量时检查错误分配的主要内容,如果未能解决你的问题,请参考以下文章

大括号封闭初始化列表?转换为矢量

段错误以及调试方法

尝试初始化结构向量时出现编译错误

如何修复 C++ 中的“分段错误”错误

检查初始化列表中的空向量

初始化具有大小的对象向量时出错