SIGABRT on throwing and catching exceptions with GCC on Mac OS X - c++

I'm currently working on proper error management in a C++ library I'm maintaining. When writing a unit test for some negative cases (i. e. testing the proper throwing of exceptions), the unit test suite simply aborted with SIGABRT. I went on a hunt and tried to boil down the error with simpler exceptions being thrown and experimenting with various catch statements. But even a catch-all block could not prevent the crash (for a MWE see below).
My setup is this: I'm working on a Mac with the most current OS X Big Sur 11.1 with the latest XCode Command Line Tools installed. I'm using GCC from Homebrew, currently v10.2.0_1.
$ g++-10 -v
Using built-in specs.
COLLECT_GCC=g++-10
COLLECT_LTO_WRAPPER=/usr/local/Cellar/gcc/10.2.0_1/libexec/gcc/x86_64-apple-darwin20/10.2.0/lto-wrapper
Target: x86_64-apple-darwin20
Configured with: ../configure --build=x86_64-apple-darwin20 --prefix=/usr/local/Cellar/gcc/10.2.0_1 --libdir=/usr/local/Cellar/gcc/10.2.0_1/lib/gcc/10 --disable-nls --enable-checking=release --enable-languages=c,c++,objc,obj-c++,fortran --program-suffix=-10 --with-gmp=/usr/local/opt/gmp --with-mpfr=/usr/local/opt/mpfr --with-mpc=/usr/local/opt/libmpc --with-isl=/usr/local/opt/isl --with-system-zlib --with-pkgversion='Homebrew GCC 10.2.0_1' --with-bugurl=https://github.com/Homebrew/homebrew-core/issues --disable-multilib --with-native-system-header-dir=/usr/include --with-sysroot=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk SED=/usr/bin/sed
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 10.2.0 (Homebrew GCC 10.2.0_1)
I also compiled GCC myself using Apples system toolchain. The output of the self-compiled GCC is this:
$ /opt/gcc/10.2.0/bin/g++-10 -v
Using built-in specs.
COLLECT_GCC=/opt/gcc/10.2.0/bin/g++-10
COLLECT_LTO_WRAPPER=/opt/gcc/10.2.0/libexec/gcc/x86_64-apple-darwin20/10.2.0/lto-wrapper
Target: x86_64-apple-darwin20
Configured with: ../configure --build=x86_64-apple-darwin20 --prefix=/opt/gcc/10.2.0 --libdir=/opt/gcc/10.2.0/lib/gcc/10 --disable-nls --enable-checking=release --enable-languages=c,c++,objc,obj-c++,fortran --program-suffix=-10 --with-system-zlib --disable-multilib --with-native-system-header-dir=/usr/include --with-sysroot=/Library/Developer/CommandLineTools/SDKs/MacOSX11.1.sdk SED=/usr/bin/sed
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 10.2.0 (GCC)
The result is still the same: exceptions abort the program.
My minimum working example is this:
#include <iostream>
#include <stdexcept>
int main()
{
try {
throw "this is an exception text";
}
catch(const char* e)
{
std::cerr << e << std::endl;
}
catch(...)
{
std::cerr << "Unknown error!" << std::endl;
}
return 0;
}
This compiles fine and produces the expected output on my Linux VM.
I'm using the following commands to compile it on my Mac:
$ g++-10 -o bin/main.o -c -std=c++11 main.cpp
$ g++-10 -o bin/main bin/main.o
$ ./bin/main
[1] 60310 abort ./bin/main
Using LLDB yields:
(lldb) run
Process 61177 launched: './bin/main' (x86_64)
Process 61177 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
frame #0: 0x00007fff202fa462 libsystem_kernel.dylib`__pthread_kill + 10
libsystem_kernel.dylib`__pthread_kill:
-> 0x7fff202fa462 <+10>: jae 0x7fff202fa46c ; <+20>
0x7fff202fa464 <+12>: movq %rax, %rdi
0x7fff202fa467 <+15>: jmp 0x7fff202f46a1 ; cerror_nocancel
0x7fff202fa46c <+20>: retq
Target 0: (main) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
* frame #0: 0x00007fff202fa462 libsystem_kernel.dylib`__pthread_kill + 10
frame #1: 0x00007fff20328610 libsystem_pthread.dylib`pthread_kill + 263
frame #2: 0x00007fff2027b720 libsystem_c.dylib`abort + 120
frame #3: 0x000000010048b00a libgcc_s.1.dylib`uw_init_context_1.cold + 5
frame #4: 0x0000000100488475 libgcc_s.1.dylib`_Unwind_RaiseException + 69
frame #5: 0x00000001001382f7 libstdc++.6.dylib`__cxa_throw + 55
frame #6: 0x0000000100003d55 main`main + 52
frame #7: 0x00007fff20343621 libdyld.dylib`start + 1
It seems to me as if another error happens during the unwind phase which then leads to the termination. Which would also explain, why no catch block is ever reached.
This is way out of my realm of expertise, so any ideas are welcome.
Edit: Updated question after the latest GCC Homebrew release.

I confirm the unexpected behaviour on Big Sur, Homebrew GCC 10.2.0_2 setup. Changing the linked brew libstdc++ to the system one (assuming the one found in /usr/lib is installed by macOS) solved the problem on my setup:
$ g++-10 main.cpp -o main -std=c++11
$ ./main
Abort trap: 6
$ otool -L main
main:
/usr/local/opt/gcc/lib/gcc/10/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.28.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1292.60.1)
/usr/local/lib/gcc/10/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
$ install_name_tool -change /usr/local/opt/gcc/lib/gcc/10/libstdc++.6.dylib /usr/lib/libstdc++.6.dylib main
$ ./main
this is an exception text
Alternatively, setting export DYLD_LIBRARY_PATH=/usr/lib before running main has the same effect.
Update: The bug has been fixed and the patch is included in brew's gcc-10.2.0_3.

Related

How to resolve `clang: error: unsupported option '-fsanitize=leak'` on apple devices

I am trying to run a simple leak check program.
#include <iostream>
int main()
{
double *ptr = new double(3.14);
}
using the command
g++ -g -fsanitize=leak -o main main.cpp
and I get the following error:
clang: error: unsupported option '-fsanitize=leak' for target 'x86_64-apple-darwin20.1.0'
I stopped using the clang that comes with Xcode and installed clang/LLVM using homebrew.
$ which clang++
/usr/local/opt/llvm/bin/clang++
clang++ --version
clang version 11.0.0
Target: x86_64-apple-darwin20.1.0
Thread model: posix
InstalledDir: /usr/local/opt/llvm/bin
EDIT: When I was using apple clang, g++ used to default to clang++. Apparently that changed when I installed llvm/clang. Thanks to #cigien for pointing it out. g++ still uses default to the compiler that that comes with Apple clang.
g++ --version
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/4.2.1
Apple clang version 12.0.0 (clang-1200.0.32.27)
Target: x86_64-apple-darwin20.1.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
According to this answer you should use:
g++-10 -g -fsanitize=leak -o main main.cpp (in this cases (with flag leak) there is no leak message for me ./main, but it compile) then it should be:
g++-10 -fsanitize=address -g main.cpp ; ASAN_OPTIONS=detect_leaks=1 ./a.out and it detect leak well.
Note, that the correct path of brew installed g++ in MacOS is:
$ which g++-10
> /usr/local/bin/g++-10
--
$ which g++
> /usr/bin/g++ //this is pseudonym of clang
The same for gcc-10 (10 is my current version. You should use your version instead of that)
If you use CMakeLists.txt file you will configure it like this:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=[sanitizer_name] [additional_options] [-g] [-OX]")
# leak sanitizer_name not works for me. should be address
And should execute cmake command like this:
cmake -DCMAKE_C_COMPILER=/usr/local/bin/gcc-10 -DCMAKE_CXX_COMPILER=/usr/local/bin/g++-10 ..
And then ASAN_OPTIONS=detect_leaks=1 ./a.out
Note, that if you open */CMakeFiles/3.18.4/CMakeCXXCompiler.cmake file you will observe the compiled info, and now it will be g++.

Simple Protocol Buffers program works when compiled with g++ but not clang++

I'm trying to use protocol buffers in a simple C++ program. When I compile with g++ the program executes and exits normally. When I compile with clang++ the program fails, complaining that pointer being freed was not allocated.
Protocol Buffer Message Definition
package test;
message Test {
required int32 id = 1;
required string name = 2;
}
Main Class
#include <iostream>
#include "test.pb.h"
int main(void) {
// Build the original message
test::Test original;
original.set_id(0);
original.set_name("original");
// Serialize the original message
int size = original.ByteSize();
char data[size];
original.SerializeToArray(data, size);
// Deserialize the data into a previously initialized message
test::Test success;
success.set_id(1);
success.set_name("success");
success.ParseFromArray(data, size);
std::cout << success.id() << ": " << success.name() << std::endl;
// Deserialize the data into an uninitialized message
test::Test failure;
failure.ParseFromArray(data, size); // FAILS HERE WITH CLANG++
std::cout << failure.id() << ": " << failure.name() << std::endl;
}
g++ Output
theisenp$ g++ test.pb.cc main.cpp -lprotobuf -o g++.out
theisenp$ ./g++.out
0: original
0: original
clang++ Output
theisenp$ clang++ test.pb.cc main.cpp -L/usr/local/lib -lprotobuf -stdlib=libstdc++ -o clang++.out
theisenp$ ./clang++.out
0: original
clang++.out(9948,0x7fff71195310) malloc: *** error for object 0x7fff72ed6330: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6
I'm new to both Protocol Buffers and Clang so it's entirely possible that I'm missing something obvious. Any ideas?
Edit
Some clarification on compiler versions. I'm running OSX Mavericks (10.9.1). By default, Mavericks maps calls to gcc and g++ to clang and clang++ respectively. I've installed gcc 4.8.2 independently and overridden the default behavior.
g++ Version
theisenp$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/local/Cellar/gcc48/4.8.2/libexec/gcc/x86_64-apple-darwin13.0.2/4.8.2/lto-wrapper
Target: x86_64-apple-darwin13.0.2
Configured with: ../configure
--build=x86_64-apple-darwin13.0.2
--prefix=/usr/local/Cellar/gcc48/4.8.2
--enable-languages=c,c++,objc,obj-c++
--program-suffix=-4.8
--with-gmp=/usr/local/opt/gmp4
--with-mpfr=/usr/local/opt/mpfr2
--with-mpc=/usr/local/opt/libmpc08
--with-cloog=/usr/local/opt/cloog018
--with-isl=/usr/local/opt/isl011
--with-system-zlib
--enable-version-specific-runtime-libs
--enable-libstdcxx-time=yes
--enable-stage1-checking
--enable-checking=release
--enable-lto
--disable-werror
--enable-plugin
--disable-nls
--disable-multilib
Thread model: posix
gcc version 4.8.2 (GCC)
clang++ Version
theisenp$ clang++ -v
Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin13.0.2
Thread model: posix
As discussed in comments, it's important that libprotobuf is compiled with the same stdlib that you use when compiling your code, since libprotobuf uses STL types (especially std::string) in its interface. If you've installed GCC 4.8, it will use GCC's libstdc++ 4.8. The Clang shipped with Xcode, meanwhile, will use whatever stdlibs ship with Xcode, so even if you tell it --stdlib=libstdc++, it may be an incompatible version.
I suspect your problem may be here:
int size = original.ByteSize();
char data[size];
Variable length arrays are not valid C++ (they are permitted in C99), they are a GCC extension.
I'd suggest using a dynamically allocated buffer and see if the problem persists. There is some discussion about clang and VLAs circa 2010 here.

Why is gcc 4.9 (trunk) so slow?

I have built an up-to-date vanilla GCC from svn with these flags:
../configure \
--enable-languages=c,c++ \
--disable-nls \
--enable-multilib \
--prefix=/opt/other/gcc-svn \
--program-suffix=-svn \
--with-system-zlib
First with clang 3.4, then I thought it may be clang's fault (with a grain of salt) and rebuilt GCC once
more with GCC 4.8.1, which led to the exact same result.
The resulting GCC is about 17 seconds slower than GCC 4.8.1 when I try to compile a C++ project with approx. 150k lines of code.
These are the build times I get (-O3):
g++ 4.9: 48 seconds
g++ 4.8: 31 seconds
clang 3.4: 13 seconds
Did I miss a configure flag or is GCC 4.9 really that much slower?!
If the compiler is slower than expected, passing the -ftime-report flag can help figuring out what's going on.
Luckily, it also helped in this case: With -ftime-report GCC printed
'Extra diagnostic checks enabled; compiler may run slowly.
Configure with --enable-checking=release to disable checks.'
Thomas has rebuilt the compiler from source accordingly and the problem is gone!

Crash during program startup when linking against Boost regex library

Our project (in C++) needs to link against boost regex so we just locate the correct compiled libboost_regex_1.45.0 and tell g++ to link against it. Compiling is successful and we just get the right executable as expected. The problem is, each time we try to run the executable, it crashes before entering main() routine.
Attaching the generated core file with gdb, the backtrace command shows there's a segmentation fault during __bultin_strlen, which is resolved to strlen##GLBC_2.2.5.
Since our executable is linked against several dynamic libraries, readelf -s is harnessed to identify the problematic symbol and it boils down to libboost_regex. However the referred symbol is already there in RHEL6 system folder /lib64/libc.so.
The question is, how can we get boost regex working properly?
OS: RHEL6.2
GCC: 4.3.2 / libstdc++6.0.13
Boost libraries is built by exactly the same toolset - user-config.bjam is customized
Static linking is not a good choice for us for various reasons.
The symbol info and ldd info is attached at https://gist.github.com/skyscribe/5184622
From the gdb backtrace, we see that the std::char_traits<char>::length method with argument \"http:\\\\/\\\\/localhostr.com\\\\/files\\\\/.+?\" is triggering the segmentation fault. g++ 4.3.2 introduced new Stack Smashing Protection features, which may interfere with the strlen length computation.
Recompile/relink your code with a recent g++ compiler and see if you solve this error. This sample code does not reproduce such error:
user#workstation ~
$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/i686-pc-cygwin/4.5.3/lto-wrapper.exe
Target: i686-pc-cygwin
Configured with: /gnu/gcc/releases/respins/4.5.3-3/gcc4-4.5.3-3/src/gcc-4.5.3/configure --srcdir=/gnu/gcc/releases/respins/4.5.3-3/gcc4-4.5.3-3/src/gcc-4.5.3 --prefix=/usr --exec-prefix=/usr --bindir=/usr/bin --sbindir=/usr/sbin --libexecdir=/usr/lib --datadir=/usr/share --localstatedir=/var --sysconfdir=/etc --datarootdir=/usr/share --docdir=/usr/share/doc/gcc4 -C --datadir=/usr/share --infodir=/usr/share/info --mandir=/usr/share/man -v --with-gmp=/usr --with-mpfr=/usr --enable-bootstrap --enable-version-specific-runtime-libs --libexecdir=/usr/lib --enable-static --enable-shared --enable-shared-libgcc --disable-__cxa_atexit --with-gnu-ld --with-gnu-as --with-dwarf2 --disable-sjlj-exceptions --enable-languages=ada,c,c++,fortran,java,lto,objc,obj-c++ --enable-graphite --enable-lto --enable-java-awt=gtk --disable-symvers --enable-libjava --program-suffix=-4 --enable-libgomp --enable-libssp --enable-libada --enable-threads=posix --with-arch=i686 --with-tune=generic --enable-libgcj-sublibs CC=gcc-4 CXX=g++-4 CC_FOR_TARGET=gcc-4 CXX_FOR_TARGET=g++-4 GNATMAKE_FOR_TARGET=gnatmake GNATBIND_FOR_TARGET=gnatbind --with-ecj-jar=/usr/share/java/ecj.jar
Thread model: posix
gcc version 4.5.3 (GCC)
user#workstation ~
$ cat test.cc
#include <iostream>
#include <string>
int main(int argc, char *argv[]) {
char * a = "\"http:\\\\/\\\\/localhostr.com\\\\/files\\\\/.+?\"";
int t = std::char_traits<char>::length (a);
std::cout << t << std::endl;
}
user#workstation ~
$ g++ -g test.cc
test.cc: In function ‘int main(int, char**)’:
test.cc:6:14: warning: deprecated conversion from string constant to ‘char*’
user#workstation ~
$ gdb a.exe
Reading symbols from /home/user/a.exe...done.
(gdb) b std::char_traits<char>::length
Breakpoint 1 at 0x4017f6: file /usr/lib/gcc/i686-pc-cygwin/4.5.3/include/c++/bits/char_traits.h, line 263.
(gdb) r
Starting program: /home/user/a.exe
[New Thread 764.0x5e4]
[New Thread 764.0x100c]
Breakpoint 1, std::char_traits<char>::length (__s=0x402080 "\"http:\\\\/\\\\/localhostr.com\\\\/files\\\\/.+?\"") at /usr/lib/gcc/i686-pc-cygwin/4.5.3/include/c++/bits/char_traits.h:263
263 { return __builtin_strlen(__s); }
(gdb) c
Continuing.
41
[Inferior 1 (process 764) exited normally]
(gdb)

Boost test crashes on exit with Clang 4.1 (LLVM 3.1svn)

Consider this simple program:
#include <string>
#include <iostream>
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE "MyTest"
#include <boost/test/unit_test.hpp>
using namespace std;
template<char* S>
void Test()
{
BOOST_REQUIRE("Boom!" != string(S));
}
char bang[] = "Bang!";
BOOST_AUTO_TEST_CASE(Boom)
{
char boom[] = "Boom!";
Test<bang>();
}
I'm on Mac OS X v10.8.2 (Mountain Lion) and have XCode 4.5 installed.
The program works when compiled with GCC, for example,
gcc test.cpp -lboost_unit_test_framework-mt -lstdc++
but it crashes when compiled with Apple Clang 4.1 (tags/Apple/clang-421.11.65) (based on LLVM 3.1svn)
clang -std=c++11 -stdlib=libc++ -lc++ test.cpp -lboost_unit_test_framework-mt
I'm using Boost 1.51.0, installed using BREW. Recompiling Boost using Clang does not help.
Is there a solution to this mystery?
./a.out
Running 1 test case...
*** No errors detected
Segmentation fault: 11
gdb ./a.out
GNU gdb 6.3.50-20050815 (Apple version gdb-1822) (Sun Aug 5 03:00:42 UTC 2012)
...
This GDB was configured as "x86_64-apple-darwin"...Reading symbols for shared libraries .... done
(gdb) r
Starting program: /private/tmp/xx/a.out
Reading symbols for shared libraries +++............................. done
Running 1 test case...
*** No errors detected
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: 13 at address: 0x0000000000000000
0x0000000100056c56 in boost::unit_test::test_unit::~test_unit ()
(gdb) where
#0 0x0000000100056c56 in boost::unit_test::test_unit::~test_unit ()
#1 0x000000010002435f in boost::unit_test::master_test_suite_t::~master_test_suite_t ()
#2 0x00000001000244dd in boost::unit_test::framework_impl::~framework_impl ()
#3 0x00007fff96179307 in __cxa_finalize ()
#4 0x00007fff9617af57 in exit ()
#5 0x00007fff944897e8 in start ()
lldb a.out
Current executable set to 'a.out' (x86_64).
(lldb) r
Process 71553 launched: '/private/tmp/xx/a.out' (x86_64)
Running 1 test case...
*** No errors detected
Process 71553 stopped
* thread #1: tid = 0x1c03, 0x0000000100056c56 libboost_unit_test_framework.dylib`boost::unit_test::test_unit::~test_unit() + 86, stop reason = EXC_BAD_ACCESS (code=13, address=0x0)
frame #0: 0x0000000100056c56 libboost_unit_test_framework.dylib`boost::unit_test::test_unit::~test_unit() + 86
libboost_unit_test_framework.dylib`boost::unit_test::test_unit::~test_unit() + 86:
-> 0x100056c56: lock
0x100056c57: xaddl %ecx, -8(%rax)
0x100056c5b: testl %ecx, %ecx
0x100056c5d: jg 0x100056c68 ; boost::unit_test::test_unit::~test_unit() + 104
clang --version
Apple clang version 4.1 (tags/Apple/clang-421.11.65) (based on LLVM 3.1svn)
Target: x86_64-apple-darwin12.2.0
Thread model: posix
Recompiling Boost with the C++11 options does the trick.
./bootstrap.sh --with-toolset=clang --prefix=/usr/local
sudo ./b2 install toolset=clang cxxflags="-std=c++11 -stdlib=libc++" linkflags="-stdlib=libc++" threading=multi
I made a mistake of using just ./b2 install last time but the install step appears to build some libraries before installing them.
I had the same issue than timlukins.
I had to do cmake .. -DBoost_USE_STATIC_LIBS=YES. But as I had other issues compiling with boost_timer for instance, I found that it was my include that was not correct.
I had to replace :
#include <boost/test/included/unit_test.hpp>
with:
#include <boost/test/unit_test.hpp>
It was working fine with gcc and VS13, but not with clang.
If it can help...
The following seems to work, but you may need the other arguments.
USER (~/tmp)
$ clang++ -pedantic test.cpp -lboost_unit_test_framework-mt
USER (~/tmp)
$ ./a.out
Running 1 test case...
*** No errors detected