This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/53225] static operator new in multiple inheritance carries incorrect type information for the class
- From: "redi at gcc dot gnu.org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Fri, 04 May 2012 22:09:10 +0000
- Subject: [Bug c++/53225] static operator new in multiple inheritance carries incorrect type information for the class
- Auto-submitted: auto-generated
- References: <bug-53225-4@http.gcc.gnu.org/bugzilla/>
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.