I have the following sample code that throws a std::ios_base::failure and tries to catch it, using clang 4.0 in c++11 mode:
#include <ios>
#include <iostream>
#include <stdexcept>
int
main()
{
try {
throw new std::ios_base::failure( "Bonkers" );
}
catch( std::ios_base::failure &e ) {
std::cout << "Failure " << e.what() << std::endl;
}
catch( ... ) {
std::cout << "Anything" << std::endl;
}
return 0;
}
I compile the program like this:
clang++-4.0 --std=c++11 -g -W -Wall ex.cc -o ex
And I get the output:
Anything
I would have expected for it to catch the specific exception. I tried the same with g++ 5.4, but the same result. Also tried without the c++11 flag, does not help either. Taking out the catch all clause gives me this:
terminate called after throwing an instance of 'std::ios_base::failure[abi:cxx11]*'
So what am I missing, and what can I do to fix this? The abi:cxx11 is also shown when I am NOT using the c++11 flag.
As mentioned in the comments, in C++ you do not need to allocate the exception via new and hence throw the pointer to the exception, as would be done in Java.
Instead you simply construct the exception and throw it:
throw std::ios_base::failure( "Bonkers" );
Then the types of the catch clause will match, and the program will behave as expected.
Related
In this simple use of C++ contracts, I get the error: no type named 'fail_fast' in namespace 'gsl'. Will try block throw the fast_fail exception or some other exception?
#define GSL_THROW_ON_CONTRACT_VIOLATION
#include <gsl/gsl>
#include <iostream>
int main(void)
{
try {
Expects(false);
}
catch(const gsl::fail_fast &e) {
std::cout << "exception: " << e.what() << '\n';
}
}
GSL_THROW_ON_CONTRACT_VIOLATION and gsl::fast_fail were removed from the Microsoft GSL starting with release v3.0.0. All contract violations result in a call to std::terminate unless you are building in kernel mode for MSVC where it invokes __fastfail.
Header file gsl_assert.h only defines gsl::fail_fast exception with GSL_THROW_ON_CONTRACT_VIOLATION defined. So it compiles now? – Serve Laurijssen
There was a period of time where gsl::fast_fail was defined only when GSL_THROW_ON_CONTRACT_VIOLATION was defined, however that was identified in #267 and subsequently fixed in #268.
Compiler:
➜ ~ /usr/bin/c++ --version
Apple clang version 11.0.0 (clang-1100.0.33.8)
Target: x86_64-apple-darwin19.0.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
Code:
#include <iostream>
#include <exception>
#include <cstdlib>
void f() {
try {
throw std::runtime_error("Exception message.");
} catch(std::runtime_error& e) {
std::cout << e.what() << std::endl;
throw;
}
}
int main() {
using namespace std;
try {
f();
} catch(std::exception& e) {
cout << e.what() << endl;
terminate();
}
return EXIT_SUCCESS;
}
I found out that if i get rid of the "terminate()" in my catch it would work but i am not sure why that is?
There are three outputs that are produced randomly:
libc++abi.dylib: terminating with uncaught exception of type std::runtime_error: Exception message.
Exception message.
Exception message.
Exception message.
libc++abi.dylib: terminating with uncaught exception of type std::runtime_error: Exception message.
Exception message.
Exception message.
Exception message.
libc++abi.dylib: terminating with uncaught exception of type std::runtime_error: Exception message.
P.S. Sorry, maybe for the incorrect question, I'm a beginner.
For starters, your regular cout print goes to stdout, but the "Terminating with ..." message goes to stderr.
What you observe stems from the fact that your terminal (or IDE) is reading these two output channels and presenting them in one place.
Depending on what algorithm your terminal/IDE uses to merge these two streams, it can happen that the stderr message appears in the places you notice.
If you instead point the streams toward the same file descriptor, your OS will take care of the merging. Run your program as follows:
./my_program 2>&1
Now your terminal will show the messages sequentially with no chance for accidental reordering.
I'm using the clang x64 compiler on MacOS 10.12. I have the following code:
try {
throw CryptoPP::Exception(CryptoPP::Exception::OTHER_ERROR, "test");
} catch(CryptoPP::Exception &e) {
std::cout << "cryptopp" << e.what() << std::endl;
} catch(std::exception &e) {
std::cout << "std" << e.what() << std::endl;
}
The CryptoPP is build as static library. When I use it in in a executable application, it works as expected.
It gets problematic when I use the CryptoPP static library in a dynamic library. Inside the library, I have that exact code (i.e. the exception does not leave the library). However, the log shows
std test
Meaning that only the second catch did actually catch the exception. How is that possible?
(This is like my other question but this one is for another thing, even if it's related)
I've got a big issue in my project. I've got a library which handle XML and can throw exception. And, using it for creating a configuration file class show my first bug : exceptions aren't handled in the library, at all, and with every exception.
In the library I wrote :
try {
throw std::exception();
}
catch (...)
{
printf("caught\n");
}
But, the exception isn't handled and call std::terminate immediately :
terminate called after throwing an instance of 'std::exception'
what(): std::exception
The compilation flags are the simplest one : -fPIC -std=c++11 -g -Wall for the library, and -std=c++11 -g -Wall for the executable (plus the libraries and variant build defines). Also, I'm using G++ 5.4.0, under Linux (Linux Mint to be precise).
This is my main :
#include "ns/core/C_Configuration.hpp"
#include <iostream>
using namespace std;
using namespace ns;
int
main (int argc, char** argv)
{
try {
C_Configuration c ("test.xml");
c.load ("test.xml");
} catch (const std::exception& ex) {
cout << ex.what () << endl;
} catch (...) {
cout << "Caught." << endl;
}
return 0;
}
The C_Configuration.hpp :
#include <string>
#include <exception>
namespace ns
{
class C_Configuration
{
public:
C_Configuration (std::string);
bool load (std::string file);
};
} // namespace ns
And, this is the C_Configuration.cpp :
#include "ns/core/C_Configuration.hpp"
#include <cstdio>
using namespace std;
namespace ns
{
C_Configuration::C_Configuration (string)
{ }
bool
C_Configuration::load (string file)
{
try {
throw exception();
} catch (const exception& ex) {
printf ("In C_Configuration : %s\n", ex.what ());
} catch (...) {
printf ("In C_Configuration : caught\n");
}
return true;
}
} // namespace ns
Buid commands :
g++ -m64 -g -shared -fPIC -std=c++11 -o libns_framework.so C_Configuration.cpp
g++ -m64 -g -L. -o exe main.cpp -lns_framework
Note : I give this example, but it works as expected, the exception is caught in the library, not like in my main project. If you want to investigate more, you can check my project code here.
The problem is when :
The try-catch block is inside the library ;
The try-catch block is outside the library ;
In any case, the exception is thrown inside the library. But, exception thrown outside are caught in the executable code :
int
main (int argc, char** argv)
{
try {
throw 1;
} catch (...) {
cout << "Caught" << endl;
}
// Useless code
return 0;
}
This code just write Caught in the output.
So, my question is simple : Is C++ exception not handled within libraries, or I just forgot a compilation flag ? I need to say in the executable code, the exceptions work fine.
Thanks for your help.
EDIT : Oh god, my bad. Problem solved. Into the deepest part of my build configuration, an ld took the place of g++. Now the exception is working fine. Thanks for you help.
Simple. Never use ld with C++. I changed all ld commands in my project to g++ but seems I forgot for this library.
In short, I was using ld for building my library but g++ for the main executable. So the exceptions worked in the executable but not in the library because ld does not includes the C++ libraries which handle the exception system.
According to gcc manual:
if a library or main executable is supposed to throw or catch exceptions, you must link it using the G++ or GCJ driver, as appropriate for the languages used in the program, or using the option -shared-libgcc, such that it is linked with the shared libgcc.
Shared libraries (in C++ and Java) have that flag set by default, but not main executables. In any case, you should use it on both.
Test Case:
lib.cpp:
#include "lib.hpp"
#include <string>
#include <iostream>
using namespace std;
int function_throws_int() {
try {
throw 2;
}
catch (...) {
cout << "int throws lib" << endl;
throw;
}
return -1;
}
int function_throws_string() {
try {
throw std::string("throw");
}
catch (...) {
cout << "throws string lib" << endl;
throw;
}
}
lib.hpp:
int function_throws_int();
int function_throws_string();
Compile command line:
g++ -m64 -g -shared-libgcc -shared -fPIC -std=c++11 -o libtest.so lib.cpp
main.cpp:
#include "lib.hpp"
#include <string>
#include <iostream>
using namespace std;
int main(int argc, char ** argv) {
try {
function_throws_int();
}
catch (const string & e) {
cout << "string caught main" << endl;
}
catch (int i) {
cout << "int caught main" << endl;
}
return 0;
}
Compile command line:
g++ -m64 -g -shared-libgcc -o main -L. main.cpp -ltest
Execute:
LD_LIBRARY_PATH=. ./main
Output:
int throws lib
int caught main
I find out there are an obviously different behaviors between boost::packaged_task and std::packaged_task. I had tested the boost version 1.55 and 1.56, and the c++11 compilers are Visual Studio 2013 and gcc(in XCode).
That is, the calling get() of the future generated from packaged_task::get_future() emits different exceptions.
Here is my simple code:
#include <boost/thread/future.hpp>
#include <future>
#include <iostream>
struct my_error {};
void throw_something()
{
throw my_error();
}
int main()
{
typedef boost::packaged_task<void> packaged_task;
packaged_task task(throw_something);
auto fu = task.get_future();
task();
try {
fu.get();
std::cout << "no exception" << std::endl;
}
catch (const my_error&) {
std::cout << "catch my_error" << std::endl;
} catch (const std::exception &e) {
std::cout << "catch std::exception: " << e.what() << std::endl;
} catch (...) {
std::cout << "catch unknown error" << std::endl;
}
std::system("pause");
return 0;
}
In Visual Studio 2013 the result is: catch std::exception: Unknown exception
and in gcc(in XCode) is: catch std::exception: std::exception
But if I changed the type of packaged_task to c++11 provided by Visual Studio 2013 or gcc, that's:
typedef std::packaged_task<void()> packaged_task;
The result becomes difference: catch my_error
I think std::packaged_task works correctly because I can catch the really type. Do I misuse boost::packaged_task?
A key difference could be that the standard library packaged_task might be statically linked, and the boost::thread version is linked in dynamically.
Throwing exceptions across dynamic library boundaries may not always work, especially when the sources weren't compiled with exactly the same compiler options.
You could
check that the libraries were compiled with the same flags
use the static version of Boost Thread library (BOOST_THREAD_STATIC, BOOST_ALL_NO_LIB might be related from a quick a google), See also http://www.boost.org/boost-build2/doc/html/bbv2/tutorial/linkage.html