Boost logo

Boost :

From: Terje Slettebø (tslettebo_at_[hidden])
Date: 2002-12-10 17:24:59


>From: "Johan Nilsson" <johan.nilsson_at_[hidden]>

> "Terje Slettebø" <tslettebo_at_[hidden]> wrote in message
> >
> > 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));

As a matter of fact, the original test I had was more elaborate, and
included calling virtual functions. However, I found that it crashed much
earlier, already in the call to dynamic_cast, where it likely tried to use a
value that pointed to outer space (the value of the "n" variable), to read
from a vtable. Therefore, I distilled it down to the above simple case. In
the case where it didn't crash, it also called the correct virtual function.

I used originally a test like this:

--- Start ---

class BaseA
{
public:
  int n;

  BaseA() : n(123) {}
};

class DerivedA : public BaseA
{
public:
  virtual ~DerivedA() {}

  virtual void f()
  {
    std::cout << "DerivedA::f()\n";
  }
};

class BaseB
{
public:
  virtual ~BaseB() {}
};

class DerivedB : public BaseB
{
public:
  int n;

  DerivedB() : n(123) {}

  virtual void f()
  {
    std::cout << "DerivedB::f()\n";
  }
};

int main()
{
DerivedA a;
DerivedB b;

void *aptr=&a;
void *bptr=&b;

DerivedA *newaptr=dynamic_void_cast<DerivedA>(aptr);
DerivedB *newbptr=dynamic_void_cast<DerivedB>(bptr);

newaptr->f();
newbptr->f();
}

--- End ---

I then trimmed it down.

Therefore, I don't think a static_cast to void *, before calling
dynamic_static_cast, will make any difference, as I used the (implicit)
conversion to void *, earlier, and in the last example. I tried it now (only
on g++), and it made no difference. It still crashed like before.

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

Actually, that made no difference, either (still on g++). However, case B
(DerivedB) above here succeeds. The difference is this:

Fails:

struct X { ~X() {} int n; };
struct Y : X {};

Succeeds:

struct X { ~X() {} };
struct Y : X { int n; };

Basically, this is messy. Don't go there. :)

> > 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?

No, I don't think you missed anything. When thinking about generalising it
to include references, as well, I came to the same as you. There's no void
&.

Regards,

Terje


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