Re: Removing data member from virtual base causes wrong member function to be called

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 6/5/07, Brian Dessent <brian@xxxxxxxxxxx> 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.

[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux