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.
std::bad_alloc is the type of the object thrown as exceptions by the allocation functions to report failure to allocate storage.
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.
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).
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With