This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]