30

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() ;
Louen
  • 3,617
  • 1
  • 29
  • 49

4 Answers4

13

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.

Mark B
  • 95,107
  • 10
  • 109
  • 188
12

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.

BartoszKP
  • 34,786
  • 15
  • 102
  • 130
John Dibling
  • 99,718
  • 31
  • 186
  • 324
6

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.

David Hammen
  • 32,454
  • 9
  • 60
  • 108
  • I know it's usually better to remove the warning cause than to live with it. What I meant by "it does only issue a warning" was that the compiler still accepted (but frowned upon) the code and compiled it into something. – Louen Oct 07 '11 at 14:44
  • 1
    What that "something" is is implementation dependent. The standard is moot when it comes to disabling RTTI. – David Hammen Oct 07 '11 at 14:46
2

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

tjysdsg
  • 656
  • 8
  • 19
  • 1
    The problem with deducing rules by compiler behavior you can hit a compiler bug and rely on wrong rules. – Slava Aug 26 '21 at 19:25