Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this code crash at the places mentioned?

Can you please elaborate why this code crashes at the places mentioned? I am a bit stumped on this. I guess that it has got something to do with sizeof(int) but I am not so sure. Can anybody explain?

class Base
{
public:
    virtual void SomeFunction() 
    {
        printf("test base\n");
    }

    int m_j;
};

class Derived : public Base {
public:
   void SomeFunction() 
   {
       printf("test derive\n");
   }

private:
   int m_i;
};

void MyWonderfulCode(Base baseArray[])
{
   baseArray[0].SomeFunction();  //Works fine
   baseArray[1].SomeFunction();  //Crashes because of invalid vfptr
   baseArray[2].SomeFunction();  //Crashes because of invalid vfptr
   baseArray[3].SomeFunction();  //Works fine
   baseArray[4].SomeFunction();  //Crashes because of invalid vfptr
   baseArray[5].SomeFunction();  //Crashes because of invalid vfptr
   baseArray[6].SomeFunction();  //Works fine
   baseArray[7].SomeFunction();  //Crashes because of invalid vfptr
   baseArray[8].SomeFunction();  //Crashes because of invalid vfptr
   baseArray[9].SomeFunction();  //Works fine
}
int _tmain(int argc, TCHAR* argv[])
{
   Derived derivedArray[10];
   MyWonderfulCode(derivedArray);
   return 0;
}
like image 454
Aamir Avatar asked Jun 25 '09 11:06

Aamir


4 Answers

sizeof(Derived) is greater than sizeof(Base). That's the reason.

Generally, indexing an array of Foo objects at index i works the following way:

element_address = array_base_address + i * sizeof(Foo)

You can see how this indexing breaks if the array elements are not of expected size. Why it works for some indices is because sometimes the calculated element address points to a valid object in memory (but it's not actually the ith object).

like image 172
laalto Avatar answered Sep 22 '22 02:09

laalto


Never treat arrays polymorphically. The C++ language does not support that. (See also this Related question.)

like image 28
Daniel Daranas Avatar answered Sep 24 '22 02:09

Daniel Daranas


Quote from this FAQ: Is array of derived same as as array of base?

Derived is larger than Base, the pointer arithmetic done with 2nd object baseArray is incorrect: the compiler uses sizeof(Base) when computing the address for 2nd object, yet the array is an array of Derived, which means the address computed (and the subsequent invocation of member function f()) isn’t even at the beginning of any object! It’s smack in the middle of a Derived object.

like image 35
Naveen Avatar answered Sep 21 '22 02:09

Naveen


Arrays can't be used for storing objects of different types or for treating objects polymorphically - store pointers instead.

Sizes of Base and Derived are different - the code seeing the Base[] array has no means to detect that it's really a Derived[] array and just indexes the array incorrectly producing all sorts of undefined behaviour.

like image 34
sharptooth Avatar answered Sep 23 '22 02:09

sharptooth