shared_ptr without RTTI?
Asked Answered
O

1

7

Im trying to use shared_ptr in an embedded project which is build with xc32 1.34 (a derivative of gcc 4.5.2). The project has RTTI disabled with -fno-rtti.

#include <memory>

Just including the header gives me the following errors:

/Applications/microchip/xc32/v1.34/bin/bin/../../lib/gcc/pic32mx/4.5.2/../../../../pic32mx/include/Cpp/memory: In member function 'virtual void* std::tr1::_Ref_count_del<_Ty, _Dx>::_Get_deleter(const std::type_info&) const':
In file included from APP/MODULES/LIGHT_MANAGER/LightManager.cpp:13:0:
/Applications/microchip/xc32/v1.34/bin/bin/../../lib/gcc/pic32mx/4.5.2/../../../../pic32mx/include/Cpp/memory:1264:39: error: cannot use typeid with -fno-rtti
/Applications/microchip/xc32/v1.34/bin/bin/../../lib/gcc/pic32mx/4.5.2/../../../../pic32mx/include/Cpp/memory: In member function 'virtual void* std::tr1::_Ref_count_del_alloc<_Ty, _Dx, _Alloc>::_Get_deleter(const std::type_info&) const':
/Applications/microchip/xc32/v1.34/bin/bin/../../lib/gcc/pic32mx/4.5.2/../../../../pic32mx/include/Cpp/memory:1299:39: error: cannot use typeid with -fno-rtti
/Applications/microchip/xc32/v1.34/bin/bin/../../lib/gcc/pic32mx/4.5.2/../../../../pic32mx/include/Cpp/memory: In function '_Dx* std::tr1::get_deleter(const std::tr1::shared_ptr<_Ty2>&)':
/Applications/microchip/xc32/v1.34/bin/bin/../../lib/gcc/pic32mx/4.5.2/../../../../pic32mx/include/Cpp/memory:1956:44: error: cannot use typeid with -fno-rtti

So what i want to know is: is it generally impossible to use shared_ptr without RTTI, or am I doing something wrong?

Overflow answered 4/7, 2016 at 9:13 Comment(12)
C++ without RTTI is not C++ any more. All (I mean all) bets are off. Who guarantees you you can use <algorithm> or <vector> or <cstdio> without RTTI?Wharfage
shared_ptr type-erases the deleter which requires RTTI. I don't think there is a way around that short of writing your own or finding an implementation that doesn't do that. Unfortunately boost::shared_ptr also supports a deleter, maybe you can find an older version that doesn't.Enolaenormity
@Enolaenormity RTTI is not required for type erasure. The usual pattern is a template wrapper class implementing an abstract class.Capitalistic
Out of curiosity: What keeps you from enabling RTTI? How much does memory usage grow or performance degrade when you do? Or is it just that people with more authority made the decision and you are stuck with it?Enolaenormity
@Capitalistic Implementing an abstract class sounds a lot like virtual functions requiring RTTI. But you are right, it can be done without, so there is a chance that another implementation just works without modifications.Enolaenormity
Having said that, g++ 5.4.0 eats shared ptrs with rtti off no problem.Wharfage
@n.m. 4.8.5 should also. According to this gcc.gnu.org/ml/gcc-patches/2014-12/msg01159.htmlHaas
@Enolaenormity I probably made an overly broad statement there. I meant that GCC's -fno-rtti (which seems to be the matter here) only removes typeid, dynamic_cast and other tools that can retrieve an object's type. Virtual functions still work fine.Capitalistic
@Enolaenormity I joined the project when everything was already set up. There is some C++ used, but the coding style generally is heavily influenced by C.Overflow
@Overflow Then, don't change this :) Or use boost lists.boost.org/Archives/boost/2006/04/103968.phpHaas
@Enolaenormity Did you just say virtual functions require RTTI?Zerla
@Zerla I thought they would, but apparently they don't. I thought without RTTI you wouldn't know which function to call and if you do you also know which type you have, but there is an error in that thinking.Enolaenormity
F
8

The problem is the get_deleter free function:

template<class D, class T> D* get_deleter(const shared_ptr<T>& p) noexcept;

Returns: If p owns a deleter d of type cv-unqualified D, returns std:addressof(d); otherwise returns nullptr. The returned pointer remains valid as long as there exists a shared_ptr instance that owns d.

Obviously, the most straightforward implementation of this is to store the typeid of the deleter in the control block. While there are other possible implementations they would (a) be more complicated, (b) lose binary compatibility with RTTI-enabled code, and (c) be against the "spirit" of -fno-rtti.

Another problematic function is dynamic_pointer_cast, which calls dynamic_cast on the stored pointer.

However, the main functionality of shared_ptr is implementable without the use of RTTI features, and indeed as Sergei Nikulov mentions above, the shared_ptr shipped with gcc 4.8.5 works with -fno-rtti, with the exception of the get_deleter and dynamic_pointer_cast functions; as long as you do not use those facilities there is no reason you should not be able to use shared_ptr. This can be contrasted with e.g. any, which is not implementable without the use of typeid.

It is the responsibility of your vendor to provide a standard library that works in all configurations of their compiler, including non-standard ones if they are supporting their use. However, if your vendor is noncooperative you still have a few options:

  • Patch the supplied standard library to remove the broken get_deleter code;
  • Use an alternative standard library (e.g. more recent libstdc++ or libc++);
  • Use an alternative smart pointer facility (e.g. Boost) or write one yourself.
Farro answered 4/7, 2016 at 11:22 Comment(1)
I realise this is an old answer but std::any is implementable without rtti. See here. As long as you dont use the type member function.Iguanodon

© 2022 - 2024 — McMap. All rights reserved.