Search code examples
c++inheritancedynamic-memory-allocationvtable

Allocating an array of Derived without new[]: Pointer to Base vtable is bad


Basically, I have a pure virtual class Base, and a concrete class Derived which inherits from Base. I then allocate a piece of memory and treat it as an array of Derived via a simple cast. Then, I populate the array using =. Finally, I loop through the array, trying to call the virtual method GetIndex that is declared in Base and defined in Derived.

The problem is that I end up getting an access violation exception trying to read the pointer to the vtable for Base (in Visual Studio debugging, this is shown as __vfptr, and it is always 0xbaadf00d).

Following is a simple example of the problem I am encountering:

#include "stdafx.h"
#include "windows.h"

struct Base
{
    virtual int GetIndex() const = 0;
};

struct Derived : public Base
{
    int index;

    Derived()
    {
        static int test = 0;
        index = test++;
    }

    int GetIndex() const
    {
        return index;
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    int count = 4;
    // Also fails with malloc
    Derived* pDerived = (Derived*)HeapAlloc(GetProcessHeap(), 0, sizeof(Derived) * count);

    for (int i = 0; i < count; i++)
    {
        Derived t;
        pDerived[i] = t;
    }

    // Should print 0 1 2 3
    for (int i = 0; i < count; i++)
    {
        Base& lc = pDerived[i];
        printf("%d\n", lc.GetIndex()); // FAIL!
    }
    return 0;
}

This behavior only occurs when allocating the memory via HeapAlloc or malloc; if new[] is used, it works fine. (Also, the cstor is called 4 times previously, so the output is 4 5 6 7.)


Solution

  • If you allocate memory without new you always need to call the constructor manually with placement new and the destructor with x->~Derived();