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.