Consider this code (badcast.cpp):
#include <exception>
#include <typeinfo>
#include <stdio.h>
class foo {
public:
virtual ~foo() {}
};
class bar: public foo {
public:
int val;
bar(): val(123) {}
};
static void
cast_test(const foo &f) {
try {
const bar &b = dynamic_cast<const bar &>(f);
printf("%d\n", b.val);
} catch (const std::bad_cast &) {
printf("bad cast\n");
}
}
int main() {
foo f;
cast_test(f);
return 0;
}
FreeBSD 9.1:
$ g++ badcast.cpp -o badcast -Wall && ./badcast
terminate called after throwing an instance of 'std::bad_cast'
what(): std::bad_cast
Abort trap (core dumped)
$ g++ badcast.cpp -o badcast -frtti -fexceptions -Wall && ./badcast
terminate called after throwing an instance of 'std::bad_cast'
what(): std::bad_cast
Abort trap (core dumped)
$ gcc -v
Using built-in specs.
Target: amd64-undermydesk-freebsd
Configured with: FreeBSD/amd64 system compiler
Thread model: posix
gcc version 4.2.1 20070831 patched [FreeBSD]
$ uname -a
FreeBSD freebsd9 9.1-RELEASE FreeBSD 9.1-RELEASE #0 r243825: Tue Dec 4 09:23:10 UTC 2012 root#farrell.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC amd64
Debian Linux 6:
$ g++ badcast.cpp -o badcast -Wall && ./badcast
bad cast
OS X 10.8:
$ g++ badcast.cpp -o badcast -Wall && ./badcast
bad cast
Why does catching bad_cast not work on FreeBSD?
As a wild guess, there’s a chance in FreeBSD you might be using LLVM’s new libc++, instead of the old GNU libstdc++. FreeBSD has been working towards switching over to the LLVM toolchain, away from GNU GPL licensed software.
Apple’s moving that way too, and in the past I’ve ran into issues developing for Mac using libc++ that libstdc++ didn’t have (especially with Boost).
You can use ldd to confirm what libraries you’re linking against:
ldd ./badcast
If it is linking against libc++, you might want to file the bug and test case with the LLVM project.
Related
I have this code:
#include <future>
#include <thread>
int main()
{
std::promise<void> p;
p.set_value();
p.get_future().get();
return 0;
}
And after compiling it with gcc it throws std::system_error:
$ g++ -o foo foo.cpp -std=c++11 -lpthread
$ ./foo
terminate called after throwing an instance of 'std::system_error'
what(): Unknown error -1
What is weird, adding zero-second sleep before creating the promise, prevents the exception:
int main()
{
std::this_thread::sleep_for(std::chrono::milliseconds(0));
std::promise<void> p;
p.set_value();
p.get_future().get();
return 0;
}
$ g++ -o foo foo.cpp -std=c++11 -lpthread
$ ./foo
$
I tried gcc 4.8.5 and 5.4.0, same results. Why does it behave like that?
This error comes from your compilation. It should be:
g++ -o foo foo.cpp -std=c++11 -pthread
The <thread> library needs this special flag -pthread but you provided -lpthread. The former compile your translation unit with the full thread support. The later only links the library, without defining the needed macros and needed tools.
On coliru:
with -pthread: http://coliru.stacked-crooked.com/a/a53bed6696bb8d83
without: http://coliru.stacked-crooked.com/a/fd972e1556f8c060
If I understood correctly from this document, it isn't prohibited to link an application built with newer compiler to a library build with an older one. Also I haven't found any information regarding ABI changes between GCC 4.8 and 4.9. However, here is a small example which causes a crash (due to an invalid vptr, apparently):
lib-48.h
#ifndef LIB_48_H
#define LIB_48_H
struct FooBase { virtual void foo() = 0; };
struct FooDerived : FooBase { virtual void foo() override {} };
void boom();
#endif // LIB_48_H
lib-48.cpp
#include "lib-48.h"
#include <memory>
void boom() {
auto x = std::make_shared<FooDerived>();
x->foo();
}
app-49.cpp
#include "lib-48.h"
#include <memory>
int main() {
std::make_shared<FooDerived>(); // Essential to reproduce
boom();
}
build & run
$ g++-4.8 -shared -fPIC -Wall -Wextra -O2 -std=c++11 lib-48.cpp -o liblib-48.so
$ g++-4.9 -std=c++11 -Wall -Wextra app-49.cpp -L. -llib-48 -Wl,-R'$ORIGIN' -o app-49
$ ./app-49
Segmentation fault (core dumped)
system information
Reproduced on x86_64 Ubuntu (both 14.04 and 16.04) with gcc 4.8.5 (Ubuntu 4.8.5-2ubuntu1~14.04.1) and gcc version 4.9.4 (Ubuntu 4.9.4-2ubuntu1~14.04.1).
Note that compiling both app and lib with the same compiler makes SIGSEGV go away. So does compiling with -O0 and few other modifications.
The question is simple: is it a bug, or am I doing something wrong?
Consider the following program:
#include <stdexcept>
#include <stdio.h>
#include <memory>
#include <list>
class Foo {
public:
Foo(){
if (s_ct==0) {throw std::bad_alloc();}
--s_ct;
fprintf(stderr, "ctor %p\n", this);
}
~Foo(){
fprintf(stderr, "dtor %p\n", this);
}
private:
static int s_ct;
};
int Foo::s_ct = 2;
int main(){
try {
std::list<std::shared_ptr<Foo>> l = {
std::make_shared<Foo>(),
std::make_shared<Foo>(),
std::make_shared<Foo>()
};
} catch (std::bad_alloc&) {
fprintf(stderr, "caught exception.\n");
}
fprintf(stderr, "done.\n");
return 0;
}
Compiled like this:
[little:~] $ g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.2) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
[little:~] $ g++ --std=c++14 -o list_init list_init.cc
[little:~] $
The output is:
[little:~] $ ./list_init
ctor 0x1294c30
ctor 0x1294c50
caught exception.
done.
[little:~] $
Notice that the destructors are not called. Valgrind correctly complains of the leak as well.
This seems to violate one of the key purposes of std::make_shared -- namely, that if another expression in the statement throws, the shared object gets properly destroyed because it is wrapped by a fully constructed shared pointer object.
Clang does what I would like here:
[little:~] $ clang++ --version
clang version 3.8.0-2ubuntu4 (tags/RELEASE_380/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
[little:~] $ clang++ --std=c++14 -o foo list_init.cc
[little:~] $ ./foo
ctor 0x1dfec30
ctor 0x1dfec50
dtor 0x1dfec50
dtor 0x1dfec30
caught exception.
done.
[little:~] $
So is this a GCC bug, or do I need to fix my program?
Turning my comment into an answer so you can mark the question as answered.
This looks to be a gcc bug
Bug 66139 - destructor not called for members of partially constructed anonymous struct/array
Note in particular the last two test cases which use std::initializer_list to illustrate the problem.
Is there a way to know if exceptions have been disabled in C++?
I'm developing an application that uses exceptions and I want to avoid having the user compile the application with exceptions disabled, like a warning that you need exceptions.
The standard certainly does not entertain such a functionality.
Assuming you are using a modern and competent compiler to compile code that contains a throw, then the compiler will error. But you can of course compile one part of the code WITH exceptions, and another without, in which case you still get exceptions thrown, but no way of catching them (since there is no catch either). So the program will probably terminate on first exception being thrown.
If you supply headers, you could just add a dummy function in an unnamed namespace:
namespace {
inline void dummy_dummy_my_thing_to_check_exceptions()
{
throw 123;
}
}
and never even call that function, it will still fail to compile.
I doubt that any compiler that lets you turn off exceptions will accept code that does this - I have tried with g++ 4.8.2, g++ 4.6.3, clang++ 3.6.0 (as of three weeks ago) and clang++ 2.9. All give an error for the above function inside a headerfile. If I remove -fno-exceptions, the code compiles and runs (with a terminate becuase the code does throw 1 in a function.
Total code:
x.h:
extern int func();
namespace {
inline void dummy_dummy_my_thing_to_check_exceptions()
{
throw 123;
}
}
x.cpp:
int func()
{
throw 1;
}
except.cpp:
#include "x.h"
int main()
{
func();
}
Compiles with:
g++ -c except.cpp && g++ except.o x.cpp
or
clang++ -c except.cpp && clang++ except.o,
but won't compile with:
g++ -c except.cpp -fno-exceptions && g++ except.o x.cpp
or
clang++ -c except.cpp -fno-exceptions && clang++ except.o.
Tried to run some sample code.
But something unexpected occured.
I wonder is there any known issus about boost.thread used with libc++ together ?
Program compiled with -std=c++11 or no option runs well.
But when I compiled with -stdlib=libc++ or -std=c++11 -stdlib=libc++
The output was like:
in main
in thread
bash: line 1: 37501 Segmentation fault: 11 ./a.out
Compiler:
Apple LLVM version 4.2 (clang-425.0.28) (based on LLVM 3.2svn)
Target: x86_64-apple-darwin12.3.0
Thread model: posix
OS: Mac OS X 10.8.3
The sample code is quite simple:
#include "stdio.h"
#include <boost/thread/thread.hpp>
class callable
{
public:
void operator()()
{
printf("in thread\n");
}
};
int main()
{
boost::thread t = boost::thread(callable());
printf("in main\n");
t.join();
return 0;
}
boost.thread is probably linked to libstdc++.
libstdc++ and libc++ have incompatible ABI. They shouldn't be used both in one program.