dynamic_cast and expections disabled

Hey,

I've rarely used dynamic_cast and mostly avoid if possible there for I have actually no idea what happens with it when expections are disabled (and/or rtti is disabled)

Today I ran into a crash on OSX with EXC_BAD_ACCESS after disabling exceptions.

1
2
3
bool runningTransition = dynamic_cast<TransitionScene*>(runningScene) != nullptr;

bool nextTransition = dynamic_cast<TransitionScene*>(nextScene) != nullptr; //<< crash here 



in this case runningScene is a nullptr which seems to be fine.
and nextScene is a valid pointer (but simply cannot be cast to a TransitionScene).

This is just a check whether the pointer can be cast to an other ptr.


https://stackoverflow.com/questions/16476613/when-dynamic-cast-will-throw-exception-in-case-used-with-pointer


Reading this it seems like it should be fine, as long as I'm not passing a invalid ptr.

(btw turning on exceptions works fine)

In general I'd like to know what happens to dynamic_cast when both rtti and expections are on, both on or just one of them?
Last edited on
Presumably if rtti is off then dynamic_cast won't have the type information it needs to work properly.
@dutch thats true, but it can be still used with some restrictions.
I kinda forgot what exact restirctions... it seems to work simply like a static_cast but as far as I remember it's sometimes still required to use dynamic_cast instead of static_cast.

probably main differences is that dynamic_cast can be still used to for casting and checking if the cast was successfull (nullptr, even without rtti), whereas static_cast will yield UB when the cast fails.
Last edited on
In general I'd like to know what happens to dynamic_cast when both rtti and expections are on, both on or just one of them?
Unfortunately this seems compiler dependent. So why not enable both?
@coder777 for rtti , fortunately is enabled (but its usually disabled for gamedev due to performance and custom reflection), I'm just curious since i totally forgot how dynamic_cast behaves without rtti.

for exceptions I'm currently trying to disable it since OSX C++17 (specifically std::variant) only works on older OS version without exceptions. (and for gamedev normally exceptions are also turned off)
The main issue I'm having right now is just the EXC_BAD_ACCESS crash for a dynamic_cast when exceptions are turned off on OSX I cannot really find anything from the standard, I'm probably blind ._.
Last edited on
Does the standard even acknowledge that exceptions and RTTI can be turned off?
@helios i don't know. I usually work on projects where they are turned off, but therefore rarely see any dynamic_casts. The only thing i can find tho is "The value of a failed cast to pointer type is the null pointer value of the required result type. A failed cast to reference type throws std::bad_cast" , so disabling exceptions shouldn't be an issue.

does this mean there is no real answer to what happens with dynamic_cast when rtti/exceptions are turned off?
Last edited on
It means that it is non-standard, and you would have to look at what your compiler says about it.

This is what GCC says.

-fno-rtti
    Disable generation of information about every class with virtual functions for use by the C++ run-time type
    identification features (dynamic_cast and typeid). If you don’t use those parts of the language, you can save
    some space by using this flag. Note that exception handling uses the same information, but G++ generates
    it as needed. The dynamic_cast operator can still be used for casts that do not require run-time type
    information, i.e. casts to void * or to unambiguous base classes.
https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Dialect-Options.html#index-fno-rtti

This means you can only use dynamic_cast to do upcasts (from derived to base) which you can do implicitly anyway, but you cannot do downcasts (from base to derived) which is usually the reason for using dynamic_cast.
Last edited on
@Peter87 yeah I now remember about the down/upcast limitation, I'm currently not using gcc anymore, I always thought this applies to all compilers ._. , msvc only says (hopefully its the right command):

1
2
3
4
5
 /GR (Enable Run-Time Type Information)
Use /GR if the compiler cannot statically resolve an object type in your code. 
You usually need the /GR option when your code uses dynamic_cast Operator or typeid.
However, /GR increases the size of the .rdata sections of your image. 
If your code does not use dynamic_cast or typeid, /GR- may produce a smaller image.


But it seems like it's no issue on msvc, and clang.

And i assume dynamic_cast still returns a nullptr when the casts fail (on all platforms).
Last edited on
Both GCC and Clang rejects the code at compile-time.

1
2
3
4
5
6
7
8
9
10
11
struct Base { virtual ~Base() = default; };
struct Derived : Base {};

int main()
{
	Derived* dp = nullptr;
	dynamic_cast<Base*>(dp); // OK
	
	Base* bp = nullptr;
	dynamic_cast<Derived*>(bp); // error: ‘dynamic_cast’ not permitted with -fno-rtti
}
@OP,

You keep asserting that dynamic_cast should work like static_cast when RTTI is turned off, citing a SO thread that doesn't mention disabling RTTI, and also never mentions static_cast.

The documentation you cite only says that /GR is needed when you use dynamic_cast, and you can use the /GR- option if you don't use dynamic_cast. So, according to the documentation that you cite, using dynamic_cast with /GR- is UB because it doesn't say what dynamic_cast does when /GR is not enabled. Assuming that it returns a null pointer in this case is not guaranteed to be a safe assumption.

Don't do that. If you need to use /GR- to reduce image size, then redesign your software so that you don't use dynamic_cast. If you need to use dynamic_cast, then don't use /GR-.

(By the way, is multiple inheritance involved at all? That could screw things up a bit, too. Just curious.)
Topic archived. No new replies allowed.