You are not logged in.

#1 2017-05-19 15:36:49

snack
Member
From: Italy
Registered: 2009-01-13
Posts: 688

[C++] dynamic_cast upcast with mismatched pointer

I'm struggling to understand the behavior of dynamic_cast in cases where the argument is a pointer to an object of a different class. For example, consider this piece of code:

#include <iostream>

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

class Derived: public Base{};

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

int main(){

    Derived *derived = new Derived;
    NotDerived *notDerived = new NotDerived;
    Derived *notDerived2 = (Derived*)(new NotDerived);
    std::cout << derived << " " <<  dynamic_cast<Base*>(derived) << std::endl;
    std::cout << notDerived << " " << dynamic_cast<Base*>(notDerived) << std::endl;
    std::cout << notDerived2 << " " << dynamic_cast<Base*>(notDerived2) << std::endl;
}

Compiling with gcc and executing gives:

0x1bd8c20 0x1bd8c20                                                                                                                                                                
0x1bd8c40 0                                                                                                                                                                        
0x1bd8c60 0x1bd8c60

From the third line one sees that dynamic_cast do not perform any runtime check when upcasting from a pointer to a derived class, even if that pointer actually points to something not belonging to the inheritance line. This is standard behavior, AFAIK. My question is: is there a way to assess at runtime that notDerived2 actually points to something that do no inherit from Base?
Thanks.

Last edited by snack (2017-05-20 09:15:56)

Offline

#2 2017-05-19 18:29:31

falconindy
Developer
From: New York, USA
Registered: 2009-10-22
Posts: 4,109
Website

Re: [C++] dynamic_cast upcast with mismatched pointer

You're using the wrong cast in your example. You can use static_cast to go from derived class to base class -- this even gets compile time checking.

You only need dynamic_cast to go from base to derived. If you attempt to call dynamic_cast on a base class and convert it to a class which is not a subclass of base, you get undefined behavior. You can get mostly compile-time checking for the purposes of ensuring that a dynamic_cast from base to derived is safe: see google's implementation of down_cast for an example.

Offline

#3 2017-05-19 18:37:14

snack
Member
From: Italy
Registered: 2009-01-13
Posts: 688

Re: [C++] dynamic_cast upcast with mismatched pointer

Hi falconindy, thanks for your reply. Actually I know that static_cast is more appropriate for upcasts, since usually upcasting is safe and does not need any runtime check. Unfortunately, I'm facing a situation where I have a pointer (notDerived2) which is a Derived* and thus is supposed to point to a Derived object, thus nothing is done at runtime to check the validity of upcating to Base; but it actually points to an object which is not a child of Base, so the cast should fail but it doesn't.
I know having a pointer which points to a completely unrelated object might sound quite weird, but that's what happens when trying to dynamically cast to a base type the content of a type erasure (see here for a brief description; by the way, that solution won't work for me since I cannot make my holder inherit from ValueType, for various reasons).

Offline

#4 2017-05-20 05:46:03

dimich
Member
From: Kharkiv, Ukraine
Registered: 2009-11-03
Posts: 39

Re: [C++] dynamic_cast upcast with mismatched pointer

Here:

Derived *notDerived2 = (Derived*)(new NotDerived)

you use C-style type cast. It's not good idea in C++ until you know what you do. It allows to cast a pointer value but behaviour of object is undefined.

Offline

#5 2017-05-20 09:15:24

snack
Member
From: Italy
Registered: 2009-01-13
Posts: 688

Re: [C++] dynamic_cast upcast with mismatched pointer

Hi dimich, that cast is obviously unsafe. I used it to mimick the real situation: I have a pointer held by a type erasure, I don't know which kind of objects it points to, so I guess it is of Base type and I need a way to verify this. Unfortunately it seems that the only cast which actually does a type check at runtime is a dynamic_cast downcast, so doing a forced C-style cast do Base or Derived and then a dynamic_cast upcast to Base will actually do no check and always succeed.

Offline

#6 2017-05-22 13:35:01

falconindy
Developer
From: New York, USA
Registered: 2009-10-22
Posts: 4,109
Website

Re: [C++] dynamic_cast upcast with mismatched pointer

snack wrote:

Hi falconindy, thanks for your reply. Actually I know that static_cast is more appropriate for upcasts, since usually upcasting is safe and does not need any runtime check. Unfortunately, I'm facing a situation where I have a pointer (notDerived2) which is a Derived* and thus is supposed to point to a Derived object, thus nothing is done at runtime to check the validity of upcating to Base; but it actually points to an object which is not a child of Base, so the cast should fail but it doesn't.
I know having a pointer which points to a completely unrelated object might sound quite weird, but that's what happens when trying to dynamically cast to a base type the content of a type erasure (see here for a brief description; by the way, that solution won't work for me since I cannot make my holder inherit from ValueType, for various reasons).

Then your type erasure class needs to give you the support you're looking for. There's no safe way to do this, otherwise.

Offline

#7 2017-05-23 01:24:58

dimich
Member
From: Kharkiv, Ukraine
Registered: 2009-11-03
Posts: 39

Re: [C++] dynamic_cast upcast with mismatched pointer

snack wrote:

My question is: is there a way to assess at runtime that notDerived2 actually points to something that do no inherit from Base?

General answer is: no.
C++ doesn't store type information inside pointers to objects, so it can't distinguish between an object and any other piece of memory at runtime.

Offline

Board footer

Powered by FluxBB