Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

bad_alloc in std::vector constructor

Tags:

c++

stl

vector

std::vector has a constructor where passing a single argument of size_type count should size the vector with count default-constructed elements. But the following code fails with a bad_alloc exception after a bad conversion:

#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;
}

When I look in the debugger, I can see an incorrect conversion has occurred on that second vector constructor:

#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

std::vector::size_type is simply a typedef from size_t. I don't understand why my defined constant BUFCOUNT results in that rolled-around value inside the constructor, and would appreciate anyone helping me find the obvious thing I'm missing.

like image 457
John S Avatar asked Jun 30 '17 12:06

John S


People also ask

What is std :: Bad_alloc ()?

std::bad_alloc is the type of the object thrown as exceptions by the allocation functions to report failure to allocate storage.

What causes std :: Bad_alloc?

std::bad_alloc is a type of exception that occurs when the new operator fails to allocate the requested space. This type of exception is thrown by the standard definitions of ​operator new (declaring a variable) and operator new[] (declaring an array) when they fail to allocate the requested storage space.

How do I fix bad Alloc?

The only thing you could do when catching std::bad_alloc is to perhaps log the error, and try to ensure a safe program termination by freeing outstanding resources (but this is done automatically in the normal course of stack unwinding after the error gets thrown if the program uses RAII appropriately).


1 Answers

BUFCOUNT is not static, which means it's an instance data member (just like bufs1, bufs2, etc. Non-static data members are initialised in the order of their declaration within the class. This means that bufs1 and bufs2 will be initialised before BUFCOUNT. The initialisation of bufs2 therefore uses the as-yet-unitialised value of BUFCOUNT (in other words, has Undefined Behaviour).

Since it makes zero sense to have each Outer object store the same BUFCOUNT integer inside it, you might want to make BUFCOUNT static.

like image 68
Angew is no longer proud of SO Avatar answered Sep 24 '22 13:09

Angew is no longer proud of SO