Search code examples
c++arraysmemory-managementbad-alloc

Initializing array inside class gives std::bad_alloc error, but outside doesn't?


I have a program with two classes (I'll call them Master and Slave), with Slave inheriting from Master. In Slave, I defined a struct, and an array of possible values of this struct type. Slave is then instantiated with the index of the array whose values I want to fill variables from the Master class.

Like so:

class Master
{
public:
    std::string _a;
    char _b;
    int _c;
    int _d;
    int _e;

    Master(std::string a, char b, int c, int d, int e)
        : _a {a}, _b {b}, _c {c}, _d {d}, _e {e} {}
};

class Slave : public Master
{
public:
    struct SlaveStruct
    {
        std::string a;
        char b;
        int c;
        int d;
        int e;
    };

    const SlaveStruct slaveArray[3]
    {
        {"name_a", 'A', 1, 2, 3},
        {"name_b", 'B', 4, 5, 6},
        {"name_c", 'C', 7, 8, 9}
    };

    Slave(int index) : Master {slaveArray[index].a, slaveArray[index].b, 
        slaveArray[index].c, slaveArray[index].d, slaveArray[index].e} {}
};

This, however, gives off a std::bad_alloc error when I try to instantiate it. Messing around, I found it works perfectly fine however if I just declare the array inside the class, and initialize it outside, as such:

class Slave : public Master
{
    //(...)

    static SlaveStruct slaveArray[3];

    //(...)
};

Slave::SlaveStruct Slave::slaveArray[3]
{
    {"name_a", 'A', 1, 2, 3},
    {"name_b", 'B', 4, 5, 6},
    {"name_c", 'C', 7, 8, 9}
};

Why is that, however? This array is 144 bytes in size, it should barely make a dent in the stack, and I'm only instantiating the class once. Tried debugging it, but after stepping in the Slave constructor it goes into a deep rabbit-hole of C++ native functions which I can't make sense of, and soon the bad_alloc error is thrown.

UPDATE: As per requested in comments, class is instantiated as such:

int main()
{
    Slave slave {1}; // For example, any index will throw the same error.
}

Platforms: Windows 10, MSVC 2017.


Solution

  • The base class constructor is called first, then members are constructed.

    In Master {slaveArray[index].a,...}, you are trying to pass slaveArray[index].a to the base class' constructor, but at this point slaveArray is not initialized yet. Your program therefore exhibits undefined behavior.

    In contrast, the static member is initialized at program startup, before main is entered. That's why your second example works fine.