http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53225

--- Comment #27 from Jonathan Wakely <redi at gcc dot gnu.org> 2012-05-04 
22:09:10 UTC ---
(In reply to comment #8)
> >No, that's not how it works. If Base::increment() writes to Base::field then 
> >it
> >is always at the same offset into the Base object. Whether that Base object 
> >is
> >a sub-object of another clas is irrelevant.
> 
> I apologize, as I don't know how else to put it but in multiple inheritance
> that statement is just plain wrong.  Fields move.  You can see it in the debug
> output at the link, the field for 'count' moved by 4 bytes from what it was in
> the parent to where it is located in the child.

Try this:
#include <iostream>
typedef unsigned int uint;

class C{ // just here to be faithful to the original code
  int y;
};

class A{
public:
  uint count;
};

class B : public C, public A{
public:
    int i;
};

int main(){
  B b;
  B* bp = &b;
  A* ap = &b;
  std::cout << "B* " << bp << '\n';
  std::cout << "A* " << ap << '\n';
  std::cout << "B::count " << &bp->count << '\n';
  std::cout << "A::count " << &ap->count << '\n';
}

The address of the same object gives two separate values. See?

B* 0x7fffb5ba8f90
A* 0x7fffb5ba8f94
B::count 0x7fffb5ba8f94
A::count 0x7fffb5ba8f94


But the count member accessed through both is the same, because there's a
different offset to access A::count inside an A (offset 0) and to access
A::count inside a B (offset 4)

So if you access bp->count and ap->count you are accessing the same member, at
the same location, but through a different offset.

So inside your operator new where you are trying to allocate a B, when you
access the count member through (A*) you get the wrong location, because you
have memory for a B (which contains an A, at offset 4) but are treating it as
though it was just an A.

Reply via email to