Boost logo

Boost :

From: Johan Nilsson (johan.nilsson_at_[hidden])
Date: 2002-12-10 10:35:22


[inlined]

"Terje Slettebø" <tslettebo_at_[hidden]> wrote in message
news:011401c2a057$f404cf30$60fb5dd5_at_pc...
> >From: "Peter Dimov" <pdimov_at_[hidden]>
>
> > From: "Johan Nilsson" <johan.nilsson_at_[hidden]>
> > >
> > > "Peter Dimov" <pdimov_at_[hidden]> wrote in message
> > > news:00bb01c2a046$671b1c20$1d00a8c0_at_pdimov2...
> > > > From: "Johan Nilsson" <johan.nilsson_at_[hidden]>
> > > > [...]
> > > > > template<typename T>
> > > > > T* dynamic_void_cast(void* pv)
> > > > > {
> > > > > struct rtti_obj__
> > > > > {
> > > > > virtual ~rtti_obj__() = 0;
> > > > > };
> > > > >
> > > > > rtti_obj__* pro = static_cast<rtti_obj__*>(pv);
> > > > >
> > > > > try
> > > > > {
> > > > > return dynamic_cast<T*>(pro);
> > > > > }
> > > >
> > > > This is not required to work. T's vtable pointer is not guaranteed
to
> be
> > > at
> > > > offset 0.
> >
> > Actually I meant *pv's vtable pointer here.
> >
> > > But I thought that it _might_ be required to be at the same offset for
T
> > as
> > > for rtti_obj. For that part, IIRC, a vtable isn't required at all, or?
> >
> > Try it (on several compilers, as some do put the vptr at offset 0.)
> >
> > struct X { int n; };
> > struct Y: public X { virtual ~Y() {} };
> >
> > Y+0: X::n
> > Y+4: vptr
> >
> > rtti_obj__+0: vptr
>
> I've tested it. Test code:
>
> --- Start ---
>
> struct X { int n; };
> struct Y: public X { public: virtual ~Y() {} };
>
> int main()
> {
> Y y;
>
> Y *yptr=dynamic_void_cast<Y>(&y);
> }
>
> --- End ---
>
> Here are the results:
>
> MSVC 6 - vptr at 0 - It works
> Intel C++ 7.0 - vptr at 0 - It works
> g++ 2.95.3 - vptr _not_ at zero - boom! :) It gives an OS protection error
> at the point of dynamic_cast
> BCB 6 - vptr _not_ at zero - boom! :) It gives an OS protection error at
the
> point of dynamic_cast
>

I'd appreciate if you could try to (1) use this instead:

Y *yptr=dynamic_void_cast<Y>(static_cast<void*>(&y));

and (2) add a virtual destructor to X. What are the results?

> Conclusion: Not recommended. :)
>
> Besides, I can't see the point in testing for bad_cast there, since it
uses
> T * (not T) in the dynamic_cast, which I think would never throw bad_cast.

How true, it was just plain ignorance from my side.

> This also means that its signature is different from dynamic_cast, and
that
> it therefore can't be used for casting references (unlike dynamic_cast).
>

That was because I couldn't imagine a 'void&', or did I miss something?

> In any case, this means it is inherently implementation-dependent and
> unsafe.
>

Basically what I suspected, thanks for taking the time.

// Johan


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk