std :: vector构造函数中的bad_alloc

Joh*_*n S 13 c++ stl vector

std::vector有一个构造函数,其中传递一个参数size_type count应该使用count默认构造的元素调整向量的大小.但是以下代码bad_alloc在转换错误后失败并出现异常:

#include <vector>

struct Inner {
  int foo;
  char buf[256];
};

template <typename Type>
struct Outer
{
  typedef std::vector<Inner> BufContainer;
  typedef typename BufContainer::size_type BufIndex;
  BufContainer bufs1;
  BufContainer bufs2;
  const BufIndex BUFCOUNT = 32;

  Outer() :
    bufs1(32),       // fine
    bufs2(BUFCOUNT)  // bad_alloc
  { }
};

int main() {
  Outer<int> outer;
}
Run Code Online (Sandbox Code Playgroud)

当我查看调试器时,我可以看到第二个向量构造函数发生了错误的转换:

#13 0x0000000000400bf1 in Outer<int>::Outer (this=0x7ffdc59570c0) at wtf.cc:22
22          bufs2(BUFCOUNT)
(gdb) down
#12 0x0000000000400d6e in std::vector<Inner, std::allocator<Inner> >::vector     (this=0x7ffdc59570d8, __n=140727918359008, __a=...) at /usr/local/gcc-4.9.1/include/c++/4.9.1/bits/stl_vector.h:278
278       : _Base(__n, __a)
(gdb) list
273        *  This constructor fills the %vector with @a __n default
274        *  constructed elements.
275        */
276       explicit
277       vector(size_type __n, const allocator_type& __a = allocator_type())
278       : _Base(__n, __a)
279       { _M_default_initialize(__n); }
(gdb) print __n
$1 = 140727918359008
Run Code Online (Sandbox Code Playgroud)

std::vector::size_type只是一个来自的typedef size_t.我不明白为什么我定义的常量BUFCOUNT导致构造函数中的滚动值,并且会感谢任何人帮助我找到我遗漏的明显事物.

Rei*_*ica 31

BUFCOUNT不是static,这意味着它是一个实例数据成员(就像bufs1,bufs2等等.非静态数据成员按照它们在类中声明的顺序进行初始化.这意味着bufs1并且bufs2将在之前 BUFCOUNT初始化.bufs2因此初始化使用as -yet-unitialised value BUFCOUNT(换句话说,具有未定义的行为).

因为让每个Outer对象在其中存储相同的BUFCOUNT整数是没有意义的,所以您可能想要创建BUFCOUNT静态.

  • 我很惊讶你的编译器没有[警告过你](http://coliru.stacked-crooked.com/a/6ab145307e84b9a2),@John.你出于某种原因关闭了你的警告吗? (4认同)
  • @cat堆栈中的垃圾是一个巨大的数字,所以分配器只是耗尽内存试图满足请求.毕竟,这就是`bad_alloc`的意思.(当然,它也可能只是一个小数字,在这种情况下不会立即出现错误.) (4认同)
  • 我也很惊讶.我刚刚在gcc 4.9.1和5.3.0下使用-Wall和-pedantic再次运行它们并且它们是静默的.但Clang 8.1.0发现了它. (3认同)
  • 我知道这将是直截了当的.我需要另一杯咖啡.非常感谢. (2认同)
  • @JohnS:小心使用gcc,在优化分析期间会执行一些"未使用"警告,因此只有在构建一些优化时才会运行.另一方面,在Clang警告和优化是独立的,因此即使在`-O0`,您也可以获得所有警告的全部好处. (2认同)