26
votes

I'm curious to know what happens when compiling code with a dynamic cast whith RTTI disabled (either with -fno-rttion GCC or with /GR- on visual studio). Does the compiler "falls back" to static_cast ? Since (at least on VS) it does only issue a warning, what will the compiled code do ?

More specifically, what bad things could happen if I compile without RTTI a code where I'm sure that there are no error possible with dynamic_cast (i.e. where dynamic_cast could be safely replaced by a static_cast) like this one :

class A{ /*...*/ } ;
class B : public A {
    int foo() { return 42 ;}
} ;
//...
A * myA = new B() ;
int bar = (dynamic_cast<B*>(myA))->foo() ;
4
Why not just try it?Eran Zimmerman Gonen
Why is your code using dynamic_cast if you're sure that static_cast can be used instead?edA-qa mort-ora-y
@edA-qamort-ora-y : I know it's better (and actually this is what I did to the offending code), I just wanted to know what would happenLouen
@EranZimmerman : I figured out that a std::__non_rtti_object was thrown, but only in some cases (I still do not know why)Louen
@EranZimmerman One would like to know if this would always work, on any platform and compiler, and not prepare a ticking bomb ready to explode when switching compiler.Antonio

4 Answers

6
votes

The easiest way to find out is to try it.

What you will find is that some of your dynamic casts will be flagged as illegal. Some won't. For example, the conversion is known at compile time when you use dynamic cast to upcast to an unambiguous base class.

Addendum
Re "Since (at least on VS) it does only issue a warning ..." Ignore warnings at your peril. The best thing to do is to ensure that your code compiles without warnings, with warning levels set very high (and possibly converted to errors). Second best is to look at each and every warning you get and ensure that nothing untoward happens. In this case, something untoward will happen. You really should not care how that untoward event is implemented. What you should care about is getting rid of it.

13
votes

Reading the standard, in 5.2.7/6 we find that unless the target is an unambiguous base of the source, source must be a polymorphic type. Then in 10.3/1

Virtual functions support dynamic binding and objectoriented programming. A class that declares or inherits a virtual function is called a polymorphic class.

In other words the standard doesn't seem to say anything about your question. In this case, the standard doesn't allow for a compiler to turn off RTTI so for each compiler you need to check its documentation to see what would happen. Based on this reading, I think this is a compiler question, not a C++ language question as the tag indicates.

Alternately you can avoid the problem completely by just using static_cast when you know it's sufficient.

9
votes

In MSVC, if your code is not compiled with RTTI enabled, a __non_rtti_object exception will be thrown, if the cast cannot be performed without a run-time check.

0
votes

Just try it:

#include <iostream>
#include <typeinfo>
#include <typeindex>
#include <memory>
#include <vector>
#include <array>
#include <string>

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

class A: public Base {
};

class B: public Base {
};

using namespace std;

int main() {
  A *a = new A;
  auto *ptr = dynamic_cast<B*>(a);

  if (!ptr)
    std::cout << "failed to cast" << std::endl;

  return 0;
}

Without -fno-rtti, the program compiles and the output is:

failed to cast

With -fno-rtti, the program failed to compile:

main.cpp:25:35: error: ‘dynamic_cast’ not permitted with -fno-rtti
     auto* ptr = dynamic_cast<B*>(a);
                                   ^

You can also test this online here: https://onlinegdb.com/pYTQu2ne2