This is the mail archive of the
gcc-help@gcc.gnu.org
mailing list for the GCC project.
Re: Removing data member from virtual base causes wrong member function to be called
On 6/5/07, Brian Dessent <brian@dessent.net> wrote:
Trent Apted wrote:
> static void* make_image() {
> return new Image();
> }
>
> int main() {
> static_cast<Event*>(make_image())->trigger();
> return 0;
> }
>
> [...]
>
> Can anyone tell me what's going on?
I think you're invoking undefined behavior because you can't use
static_cast to downcast a pointer like that in the face of virtual
inheritance. You have to use dynamic_cast. I don't really understand
why you're intentionally obscuring things with the void* business,
A good point -- I had thought it necessary, as I am pushing things of
type SDL_UserEvent into the SDL event queue -- a C interface,
requiring void*. However, you've made me think about it and clued me
in on a different strategy -- instead casting the Event* to a void* in
the struct, I can convert some simpler struct to void* that just holds
an Event* data member. Thanks!
Although, I now have to create 2 objects for each event using new
(unless I assume sizeof(EventHandle) == sizeof(void*) and do some
reinterpret_cast ing). i.e. it becomes:
static void* make_image() {
EventHandle *eh = new EventHandle;
eh->ref = new Image();
return eh;
}
int main() {
static_cast<EventHandle*>(make_image())->ref->trigger();
return 0;
}
this seems to work.
but if you change it to "dynamic_cast<Event*>((Image
*)make_image())->trigger()" you get the desired behavior.
Unfortunately, I can't do this, because the code that calls trigger()
doesn't know anything about Image -- only Events (make_image is
potentially any function that returns something derived from Event) --
and I can't dynamic_cast with a void*, until it has some info about a
parent type.
The fact that
the undefined behavior just happens to depend on the layout of Resource
is incidental.
I had hoped virtual inheritance might remove the conflict between
layout/order of the multiple bases. Indeed, it seems to, but only when
there is a data member, which makes me think something else might be
at work here..
A warning might also be nice -- "implicit cast to void* from type with
virtual bases may cause undefined behaviour" -- but I thought I'd make
sure I'm not missing something obvious before bugging the devs...
*laments the hours spent debugging* ;-)
- Trent.