Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

dynamic_cast vs dynamic library boundaries

Tags:

c++

I'm reading ``C++ GUI Programming with Qt 4", where I found the following statement

Unlike the Standard C++ dynamic_cast(), Qt’s qobject_cast() works correctly across dynamic library boundaries.

A similar statement appears in the official Qt documentation at

https://doc.qt.io/qt-5/qobject.html#qobject_cast

What does it mean? Where exactly we cannot use dynamic_cast in C++ ? And what about virtual functions? Is it safe to use them with dynamically linked libraries?

like image 722
Adrian Avatar asked Jul 01 '19 10:07

Adrian


People also ask

When to use dynamic cast?

dynamic_cast −This cast is used for handling polymorphism. You only need to use it when you're casting to a derived class. This is exclusively to be used in inheritence when you cast from base class to derived class.

Is Static_cast faster than dynamic_cast?

While typeid + static_cast is faster than dynamic_cast , not having to switch on the runtime type of the object is faster than any of them.

When to use dynamic cast Cpp?

In C++, dynamic casting is mainly used for safe downcasting at run time. To work on dynamic_cast there must be one virtual function in the base class. A dynamic_cast works only polymorphic base class because it uses this information to decide safe downcasting.

Is dynamic_cast a code smell?

Yes, dynamic_cast is a code smell, but so is adding functions that try to make it look like you have a good polymorphic interface but are actually equal to a dynamic_cast i.e. stuff like can_put_on_board .


1 Answers

In concept, dynamic_cast can work across module boundaries. But, some compilers/linkers cut corners in the name of performance. One of the ways to improve performance when loading shared libraries is to make as few symbols visible to other libraries as possible. This reduces the amount of work the loader has to do because it doesn't have to resolve as many symbols. RTTI symbols are on the chopping block and are among those not exposed to other modules by default. GCC's documentation describes this and the workaround here.

Unfortunately, this makes things a mess when it comes to RTTI. The module that constructed an object and the one performing the dynamic_cast might hold their own, otherwise identical, RTTI symbols for a type. This makes them appear as different types when the dynamic_cast is performed in a different module, causing dynamic_cast to unexpectedly return nullptr, or throw std::bad_cast for references.

Special care is required when linking and when calling dlopen() for the loader to know to resolve RTTI symbols between modules on module load.

Also, historically Qt has supported platforms which either do not support RTTI, or where RTTI would have too much of an overhead. So, qobject_cast was invented to remove the reliance on RTTI altogether while still providing a way to cast between polymorphic types.

To answer your other questions:

  • You can use dynamic_cast anywhere RTTI is available but dynamic linking can make this difficult.
  • Virtual functions work fine in these scenarios as the loader will resolve the symbols of functions.
like image 75
Sean Cline Avatar answered Nov 15 '22 14:11

Sean Cline