Skip to content

Allow compilation with -fno-rtti #44

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed

Allow compilation with -fno-rtti #44

wants to merge 1 commit into from

Conversation

mattfbacon
Copy link

Using typeid doesn't seem to work even if the result can (and is) evaluated at compile-time. Specifically, typeid(int) or similar results in a compilation error.

Since this data is only used to make better error messages, and therefore is not crucial, replace the type string with "(no rtti)" when RTTI is disabled.

@d-frey d-frey self-assigned this Sep 13, 2021
@d-frey d-frey closed this in 8bd77ab Sep 13, 2021
@d-frey
Copy link
Member

d-frey commented Sep 13, 2021

Thanks for the suggestion. As you can see, I committed a different approach: We don't need RTTI anymore, but we can still demangle the types :)

@mattfbacon
Copy link
Author

I saw some information about this but it seemed really complicated. I'm glad you did this because it will be helpful in my project with RTTI disabled.

@d-frey
Copy link
Member

d-frey commented Sep 13, 2021

I never had a use-case for disabling RTTI, and I was under the impression that people that want/have to disable RTTI usually also can't use exceptions. So, first of all I'm happy it helped you, but I'm also curious: What environment allows exceptions but no RTTI?

@mattfbacon
Copy link
Author

mattfbacon commented Sep 14, 2021

It's not that they're allowed or not per se. I just don't like the overhead that RTTI incurs. IIRC (and I'm not very sure because there's not much info), RTTI adds a vtable pointer to every object. I never use RTTI—in fact, I think it is squarely against proper OOP principles—so I have no reason to incur this overhead.

@d-frey
Copy link
Member

d-frey commented Sep 14, 2021

The overhead of RTTI is generally very small, as it adds a pointer to the vtable if and only if the class already has a vtable. Classes without a vtable won't get one just because you enabled RTTI. There will be a typeid-structure (mostly the (mangled) name) for every class, but the compiler simply references this statically without dynamic lookup for non-virtual classes, so no vtable is needed/added in that case. And the vtable for virtual classes is shared between all objects of that class, meaning there is no per-object overhead added by RTTI, only a per-class overhead.

@mattfbacon
Copy link
Author

Alright, that's good to know. I'm not sure why I couldn't find that information online. Seems like an implementation detail.

On the other hand, does it increase the size of the binary?

@d-frey
Copy link
Member

d-frey commented Sep 15, 2021

It does increase the binary size, but again it's not a big difference in my experience. I just ran a small experiment on a binary from the PEGTL: With RTTI, it was 179376 bytes long, with -fno-rtti it went down to 179064 bytes on my system. GCC 11, -O3. (abnf2pegtl from the examples)

@mattfbacon
Copy link
Author

Interesting. Thanks.

@d-frey
Copy link
Member

d-frey commented Sep 15, 2021

And there is a problem: std::shared_ptr requires RTTI support, at least when you use std::get_deleter - which our connection pool does. See https://stackoverflow.com/questions/38180899/shared-ptr-without-rtti

So without RTTI-support the connection pool can not be used. II'll take care of it maybe tomorrow, for today I'm too tired.

@mattfbacon
Copy link
Author

Forget it. I'll just enable RTTI. I thought this was much simpler than it is. I don't want to waste your time.

@mattfbacon
Copy link
Author

https://en.cppreference.com/w/cpp/memory/shared_ptr/get_deleter

Compiling the example with -fno-rtti, get_deleter doesn't work, but the proper destructor is called. However, do you alias the shared_ptr? If not, why is it necessary.

@mattfbacon
Copy link
Author

I'm confused. In https://en.cppreference.com/w/cpp/memory/shared_ptr, they say that the control block includes the deleter, but if that were true then why is RTTI required at all? Can't get_deleter just fetch the deleter from the control block?

@d-frey
Copy link
Member

d-frey commented Sep 16, 2021

It's explained in the StackOverflow link I posted. It would be possible to implement get_deleter without RTTI, but it wasn't done and now it would break the ABI.

@mattfbacon
Copy link
Author

Ah. Unfortunate. Anyway, I've enabled RTTI. I didn't used connection pool in the first place so there were no assertions that failed, but nonetheless I will enable it.

That makes me curious though. Would it be possible to implement our own, similar but different version of shared_ptr, that doesn't use RTTI?

@d-frey
Copy link
Member

d-frey commented Sep 16, 2021

That's possible, but I don't want to unnecessarily introduce types that resemble standard types. Remember the type gets exposed in our API, it's not just an implementation detail. I'll revert the changes to demangle and simply require RTTI. As mentioned earlier, I only encountered people so far that couldn't use both RTTI and exceptions. And our design simply relies on exceptions, I don't feel like changing that. So, RTTI it is 🤷🏻‍♂️

d-frey added a commit that referenced this pull request Sep 16, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

2 participants