[libcxx-dev] Exception handling with RTTI disabled on macOS

John McCall via libcxx-dev libcxx-dev at lists.llvm.org
Tue Jan 26 11:13:23 PST 2021


On 26 Jan 2021, at 10:25, Ilia K wrote:
> Hi!
>
> It turned out that I cannot catch `std::bad_alloc&` thrown by the 
> `operator
> new` when compiling 1.cpp with -fno-rtti and linking against system's
> libc++.1.dylib/libc++abi.dylib on macOS. This scenario works on Linux, 
> and
> according to the official libc++ page it is supported ("However 
> linking
> against it with -fno-rtti is supported", https://libcxx.llvm.org/), 
> however
> the following code is aborted due to an unhandled exception:
>
> ```1.cpp
> #include <cstdio>
> #include <new>
>
> int main() {
>     try {
>         ::operator new(-1);
>     } catch (std::bad_alloc& e) {
>         printf("caught %s\n", e.what());
>     }
>     return 0;
> }
> ```
>
> Compile & run:
> ```
> $ clang++ -fno-rtti 1.cpp -o 1_no_rtti
> $ ./1_no_rtti
> libc++abi.dylib: terminating with uncaught exception of type
> std::bad_alloc: std::bad_alloc
> Abort trap: 6
> ```
>
> I know about similar issues with exceptions when -fno-rtti on macOS
> (Polymorphically catching an exception in a -fno-rtti shared library 
> on Mac
> OS X
> https://stackoverflow.com/questions/3638237/polymorphically-catching-an-exception-in-a-fno-rtti-shared-library-on-mac-os-x,
> Problems throwing and catching exceptions on OS X with -fno-rtti
> https://stackoverflow.com/questions/21737201/problems-throwing-and-catching-exceptions-on-os-x-with-fno-rtti).
> There was an issue in Android NDK with exceptions when -flto=thin and 
> it
> was said that "The problem is that we have multiple copies of a 
> symbol,
> where one of them is strong, and the others are linkonce_odr"
> https://github.com/android/ndk/issues/1046#issuecomment-514469559 
> (fixed
> now https://reviews.llvm.org/D61255).
>
> Can anyone shed some light on it? It seems like a bug at the moment, 
> and if
> your code uses any of libc++.1.dylib/libc++abi.dylib system libraries 
> on
> macOS, you must leave RTTI enabled, except you have turned exceptions 
> off
> as well.

Mechanically, the problem here is that exceptions rely on RTTI, so
combining `-fno-rtti` with `-fexceptions` forces the compiler to make
an awkward decision about whether to expect that classes with key
functions emit their RTTI objects eagerly.  If the compiler trusts
classes to do this, then you can’t catch and throw exceptions of your
own class types that happen to have key functions; if the compiler
doesn’t trust classes to do this, then you can’t catch and throw
exceptions of system classes like `std::bad_alloc` (or any class that
happens to have a key function and is compiled with RTTI enabled).
The traditional decision is to favor the first, and we can’t really
change that.

Darwin is stricter about RTTI object matching than other platforms,
and we’re also not going to change that.

Ultimately, `-fno-rtti -fexceptions` is only a semi-supported
configuration.  It causes language implementation problems which it
becomes your responsibility to work around.  In this case, you can do
that by catching the exception in a file that does not disable RTTI.

John.

>
> FYI, the difference between non-RTTI (./1_no_rtti) and the default
> (./1_rtti, with RTTI) Mach-O executables:
> ```
> $ diff <(nm -C 1_no_rtti) <(nm -C 1_rtti)
> 1c1
> < 0000000100003f48 s GCC_except_table0
> ---
>> 0000000100003f68 s GCC_except_table0
> 4,9c4
> < 0000000100004028 S typeinfo for std::bad_alloc
> < 0000000100004018 S typeinfo for std::exception
> < 0000000100003f74 S typeinfo name for std::bad_alloc
> < 0000000100003f81 S typeinfo name for std::exception
> <                  U vtable for __cxxabiv1::__class_type_info
> <                  U vtable for __cxxabiv1::__si_class_type_info
> ---
>>                  U typeinfo for std::bad_alloc
> 11c6
> < 0000000100003ed0 t ___clang_call_terminate
> ---
>> 0000000100003ef0 t ___clang_call_terminate
> 17c12
> < 0000000100003e20 T _main
> ---
>> 0000000100003e40 T _main
> $ diff <(clang++ -fno-rtti 1.cpp -S -o -) <(clang++ 1.cpp -S -o -)
> 143,169d142
> <       .section        __TEXT,__const
> <       .globl  __ZTSSt9bad_alloc       ## @_ZTSSt9bad_alloc
> <       .weak_definition        __ZTSSt9bad_alloc
> < __ZTSSt9bad_alloc:
> <       .asciz  "St9bad_alloc"
> <
> <       .globl  __ZTSSt9exception       ## @_ZTSSt9exception
> <       .weak_definition        __ZTSSt9exception
> < __ZTSSt9exception:
> <       .asciz  "St9exception"
> <
> <       .section        __DATA,__const
> <       .globl  __ZTISt9exception       ## @_ZTISt9exception
> <       .weak_definition        __ZTISt9exception
> <       .p2align        3
> < __ZTISt9exception:
> <       .quad   __ZTVN10__cxxabiv117__class_type_infoE+16
> <       .quad   __ZTSSt9exception
> <
> <       .globl  __ZTISt9bad_alloc       ## @_ZTISt9bad_alloc
> <       .weak_definition        __ZTISt9bad_alloc
> <       .p2align        3
> < __ZTISt9bad_alloc:
> <       .quad   __ZTVN10__cxxabiv120__si_class_type_infoE+16
> <       .quad   __ZTSSt9bad_alloc
> <       .quad   __ZTISt9exception
> <
> ```
>
> Linked issues: https://reviews.llvm.org/D46665,
> https://reviews.llvm.org/D47092,
> https://reviews.llvm.org/rG2405bd6898151e0a7ffede78b0d0c7c85c0b66d3,
> https://github.com/Amanieu/asyncplusplus/commit/2360c8993951afab67ab0414288dacae1dbd7195
>
> -- 
> - Ilia


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/libcxx-dev/attachments/20210126/063c836f/attachment-0001.html>


More information about the libcxx-dev mailing list