I am trying to use the following code to test "set_unexpected()". I expect the code will generate an output like:
In function f(), throw const char* object
Call to my_unexpected
Exception in main(): Exception thrown from my_unexpected
But I got a run-time error: "This application has requested the Runtime to terminate it in an unusual way." So, what would be the problem? Thanks
struct E {
const char* message;
E(const char* arg) : message(arg) { }
};
void my_unexpected() {
cout << "Call to my_unexpected" << endl;
throw E("Exception thrown from my_unexpected");
}
void f() throw(E) {
cout << "In function f(), throw const char* object" << endl;
throw("Exception, type const char*, thrown from f()");
}
int _tmain(int argc, _TCHAR* argv[])
{
set_unexpected(my_unexpected);
try {
f();
}
catch (E& e) {
cout << "Exception in main(): " << e.message << endl;
}
return 0;
}
Visual C++ does not implement correctly exception specifications. As stated here,
Visual C++ departs from the ANSI Standard in its implementation of exception specifications.
and in particular
throw(type) - The function can throw an exception of type type. However, in Visual C++ .NET, this is interpreted as throw(...).
Also here:
Function exception specifiers other than throw() are parsed but not used.
Because of this, your terminate handler is never called, and since no handlers for const char * are present in your code the exception is not caught and the application terminates abnormally.
Anyway, keep in mind that exception specifications different from throw() are generally considered a bad idea, and actually the new C++ standard (C++11) deprecates them, introducing noexcept for what throw() was used.
Related
Considering this silly looking try-catch chain:
try {
try {
try {
try {
throw "Huh";
} catch(...) {
std::cout << "what1\n";
}
} catch(...) {
std::cout << "what2\n";
}
} catch(...) {
std::cout << "what3\n";
}
} catch(...) {
std::cout << "what4\n";
}
its output will surely be (and is) what1, because it will be caught by the closest matching catch. So far so good.
However, when I try to create a constructor for a class that tries to initialise a member via member initialiser list (which will result in an exception being raised) like so:
int might_throw(int arg) {
if (arg < 0) throw std::logic_error("que");
return arg;
}
struct foo {
int member_;
explicit foo(int arg) try : member_(might_throw(arg)) {
} catch (const std::exception& ex) { std::cout << "caught1\n"; }
};
int main() {
try {
auto f = foo(-5);
} catch (...) { std::cout << "caught2\n"; }
}
The output of the program is now:
caught1
caught2
Why is the exception being rethrown here (I assume that it is, otherwise why would two catches fire?)? Is this mandated by the standard or is it a compiler bug? I am using GCC 10.2.0 (Rev9, Built by MSYS2 project).
cppreference has this to say about a function-try-block (which is what we have here):
Every catch-clause in the function-try-block for a constructor must terminate by throwing an exception. If the control reaches the end of such handler, the current exception is automatically rethrown as if by throw.
So there we have it. Your exception is automatically rethrown when the catch on the constructor's member initialization list exits. I guess the logic is that your constructor is deemed to have failed so (after the exception handler in the constructor performs any cleanup, perhaps) the exception is automatically propagated to the caller.
While the other answer gives a great official explanation, there is also a really intuitive way to see why things have to behave this way: Consider the alternative.
I've replaced the int with a string to make the issue obvious, but the same principle applies with arithmetic types as well.
std::string might_throw(const std::string& arg) {
if (arg.length() < 10) throw std::logic_error("que");
return arg;
}
struct foo {
std::string member_;
explicit foo(const std::string& arg) try : member_(might_throw(arg)) {
} catch (const std::exception& ex) { std::cout << "caught1\n"; }
};
int main() {
try {
auto f = foo("HI");
std::cout << f.member_ << "\n"; // <--- HERE
} catch (...) { std::cout << "caught2\n"; }
}
What would be supposed to happen if the exception did not propagate?
Not only did arg never make it to member, but the string's constructor never got invoked at all. It's not even default constructed. Its internal state is completely undefined. So the program would be simply broken.
It's important that the exception propagates in such a way to avoid messes like this.
To pre-empt the question: Remember that the reason initializer lists are a thing in the first place is so that member variables can be initialized directly without having their default constructor invoked beforehand.
I have a very poor understanding of exception handling(i.e., how to customize throw, try, catch statements for my own purposes).
For example, I have defined a function as follows: int compare(int a, int b){...}
I'd like the function to throw an exception with some message when either a or b is negative.
How should I approach this in the definition of the function?
Simple:
#include <stdexcept>
int compare( int a, int b ) {
if ( a < 0 || b < 0 ) {
throw std::invalid_argument( "received negative value" );
}
}
The Standard Library comes with a nice collection of built-in exception objects you can throw. Keep in mind that you should always throw by value and catch by reference:
try {
compare( -1, 3 );
}
catch( const std::invalid_argument& e ) {
// do stuff with exception...
}
You can have multiple catch() statements after each try, so you can handle different exception types separately if you want.
You can also re-throw exceptions:
catch( const std::invalid_argument& e ) {
// do something
// let someone higher up the call stack handle it if they want
throw;
}
And to catch exceptions regardless of type:
catch( ... ) { };
Though this question is rather old and has already been answered, I just want to add a note on how to do proper exception handling in C++11:
Use std::nested_exception and std::throw_with_nested
It is described on StackOverflow here and here, how you can get a backtrace on your exceptions inside your code without need for a debugger or cumbersome logging, by simply writing a proper exception handler which will rethrow nested exceptions.
Since you can do this with any derived exception class, you can add a lot of information to such a backtrace!
You may also take a look at my MWE on GitHub, where a backtrace would look something like this:
Library API: Exception caught in function 'api_function'
Backtrace:
~/Git/mwe-cpp-exception/src/detail/Library.cpp:17 : library_function failed
~/Git/mwe-cpp-exception/src/detail/Library.cpp:13 : could not open file "nonexistent.txt"
Just add throw where needed, and try block to the caller that handles the error. By convention you should only throw things that derive from std::exception, so include <stdexcept> first.
int compare(int a, int b) {
if (a < 0 || b < 0) {
throw std::invalid_argument("a or b negative");
}
}
void foo() {
try {
compare(-1, 0);
} catch (const std::invalid_argument& e) {
// ...
}
}
Also, look into Boost.Exception.
You could define a message to throw when a certain error occurs:
throw std::invalid_argument( "received negative value" );
or you could define it like this:
std::runtime_error greatScott("Great Scott!");
double getEnergySync(int year) {
if (year == 1955 || year == 1885) throw greatScott;
return 1.21e9;
}
Typically, you would have a try ... catch block like this:
try {
// do something that causes an exception
}catch (std::exception& e){ std::cerr << "exception: " << e.what() << std::endl; }
Adding to this answer, as it doesn't seem advantageous to create another answer for this Q&A at this time.
In the case where you create your own custom exception, that derives from std::exception, when you catch "all possible" exceptions types, you should always start the catch clauses with the "most derived" exception type that may be caught. See the example (of what NOT to do):
#include <iostream>
#include <string>
using namespace std;
class MyException : public exception
{
public:
MyException(const string& msg) : m_msg(msg)
{
cout << "MyException::MyException - set m_msg to:" << m_msg << endl;
}
~MyException()
{
cout << "MyException::~MyException" << endl;
}
virtual const char* what() const throw ()
{
cout << "MyException::what" << endl;
return m_msg.c_str();
}
const string m_msg;
};
void throwDerivedException()
{
cout << "throwDerivedException - thrown a derived exception" << endl;
string execptionMessage("MyException thrown");
throw (MyException(execptionMessage));
}
void illustrateDerivedExceptionCatch()
{
cout << "illustrateDerivedExceptionsCatch - start" << endl;
try
{
throwDerivedException();
}
catch (const exception& e)
{
cout << "illustrateDerivedExceptionsCatch - caught an std::exception, e.what:" << e.what() << endl;
// some additional code due to the fact that std::exception was thrown...
}
catch(const MyException& e)
{
cout << "illustrateDerivedExceptionsCatch - caught an MyException, e.what::" << e.what() << endl;
// some additional code due to the fact that MyException was thrown...
}
cout << "illustrateDerivedExceptionsCatch - end" << endl;
}
int main(int argc, char** argv)
{
cout << "main - start" << endl;
illustrateDerivedExceptionCatch();
cout << "main - end" << endl;
return 0;
}
NOTE:
The proper order should be vice-versa, i.e.- first you catch (const MyException& e) which is followed by catch (const std::exception& e).
As you can see, when you run the program as is, the first catch clause will be executed (which is probably what you did NOT want in the first place).
Even though the type caught in the first catch clause is of type std::exception, the "proper" version of what() will be called - cause it is caught by reference (change at least the caught argument std::exception type to be by value - and you will experience the "object slicing" phenomena in action).
In case that the "some code due to the fact that XXX exception was thrown..." does important stuff WITH RESPECT to the exception type, there is misbehavior of your code here.
This is also relevant if the caught objects were "normal" object like: class Base{}; and class Derived : public Base {}...
g++ 7.3.0 on Ubuntu 18.04.1 produces a warning that indicates the mentioned issue:
In function ‘void illustrateDerivedExceptionCatch()’:
item12Linux.cpp:48:2: warning: exception of type ‘MyException’ will be caught
catch(const MyException& e)
^~~~~
item12Linux.cpp:43:2: warning: by earlier handler for ‘std::exception’
catch (const exception& e)
^~~~~
Again, I will say, that this answer is only to ADD to the other answers described here (I thought this point is worth mentioning, yet could not depict it within a comment).
I am learning C++ and I am experiencing when I try and create my own exception and throw them on Linux.
I've created a small test project to test my implementation and below is my exception class header file.
class TestClass : public std::runtime_error
{
public:
TestClass(char const* const message) throw();
virtual char const* what() const throw();
};
The source file for the exception class is
using namespace std;
TestClass::TestClass(char const* const message) throw()
: std::runtime_error(message)
{
}
char const * TestClass::what() const throw()
{
return exception::what();
}
In my main app, I am calling a function which throws my exception and catches it in a try/catch as follows:
void runAFunctionAndthrow();
/*
*
*/
int main(int argc, char** argv) {
try
{
cout << "About to call function" << endl;
runAFunctionAndthrow();
}
catch (TestClass ex)
{
cout << "Exception Caught: " << ex.what() << endl;
}
return 0;
}
void runAFunctionAndthrow()
{
cout << "going to run now. oh dear I need to throw an exception" << endl;
stringstream logstream;
logstream << "This is my exception error. :(";
throw TestClass(logstream.str().c_str());
}
When I run I'm expecting to get the following output:
About to call function
Going to run now. oh dear I need to throw an exception
Exception Caught: This is my exception error. :(
Instead what I am getting is
About to call function
going to run now. oh dear I need to throw an exception
Exception Caught: std::exception
Notice the last line it says std::exception instead of my actual exception message "This is my exception error".
Why is this, it works OK on Windows but on Linux it does this.
From what I've seen on various posts what I've done is correct so what am I missing.
Your what() returns:
return exception::what();
The return value from std::exception::what() is specified as follows:
Pointer to a null-terminated string with explanatory information.
That's it. Nothing more, nothing else. The text you're showing certainly qualifies as an "explanatory information". And this is the only requirement for the return value of what() (except for one other one which is not germane here).
In other words, C++ does not guarantee the exact contents of what you get with what(). what() you see is what() you get, as the saying goes.
If you want your exception to describe itself, in some way, it's up to you to implement that, as part of your what().
You need your own implementation of what() method or use std::runtime_error::what() as written in comments
Say:
class TestClass : public std::runtime_error
{
std::string what_message;
public:
const char* what() override
{
return what_message.c_str();
}
};
Also, better use noexcept instead of throw() and only after you read about them - link.
And in your try-catch:
catch (const TestClass& myException)
Instead of catch(TestClass myException) - otherwise you do an implicit copy which can potentially result in an exception throw. It also breaks the polymorphism: if you want to catch pure virtual interface implementation instance, you would need to use a reference.
You need a way to specify a custom error message to std::exception which afaik is not allowed. See this for a possible solution.
First of most of the info about the answer had been given by Sam Varshavchik
But I want to add one thing
When throwing and catching A good rule is
"Throw by value catch by reference "
So your throw was fine as:
void runAFunctionAndthrow()
{
cout << "going to run now. oh dear I need to throw an exception" << endl;
stringstream logstream;
logstream << "This is my exception error. :(";
throw **TestClass(logstream.str().c_str())**;
}
used an implicit conversion to TestClass and then it got passed by value.
the Key point in that rule is to minimize memory allocating handling between different stack frames
your catch on the other hand dosen't follow the rule (since you catch by value):
catch (TestClass ex)
{
cout << "Exception Caught: " << ex.what() << endl;
}
the catch should be (const TestClass& ex)
the key point in this rule is implicit conversion between base class and derived class.
I am writing a program in C++ which handles errors via throwing strings (either std::string or const char*), like so :
if (/* failure condition 1 */)
throw std::string("Error 1 : ...") + std::to_string(foo);
if (/* failure condition 2 */)
throw "Error 2 : ...";
Then I would catch them this way :
try {
thisIsLikelyToThrowErrors();
} catch (const std::string& e) {
std::cerr << ":( " << e << std::endl;
} catch (const char* e) {
std::cerr << ":( " << e << std::endl;
}
I would like to avoid writing the same line twice, by forwarding the string from the first catch block to the second one :
try {
thisIsLikelyToThrowErrors();
} catch (const std::string& e) {
throw e.c_str(); // Does not work
} catch (const char* e) {
std::cerr << ":( " << e << std::endl;
}
However this code won't work, the thrown char const* simply won't be catched.
Is there a way to do this?
Thanks :)
No, you cannot do this.
[C++14: 15.1/1]: When an exception is thrown, control is transferred to the nearest handler with a matching type (15.3); “nearest” means the handler for which the compound-statement or ctor-initializer following the try keyword was most recently entered by the thread of control and not yet exited.
You would have to nest entire try/catch pairs:
try {
try {
thisIsLikelyToThrowErrors();
}
catch (const std::string& e) {
throw e.c_str(); // Does not work
}
}
catch (const char* e) {
std::cerr << ":( " << e << std::endl;
}
Ew!
But now you have another problem, in that the std::string e dies after you've thrown its C-string buffer (it'd stay alive if you re-threw it). Probably try to avoid this in general, eh?
Throw actual exceptions, instead.
You can handle the common setup in an independent function externally, calling it from your catches clauses.
In your example, you can do:
inline void HandleStringyException(const char* excStr)
{
//do something
}
Then:
try {
thisIsLikelyToThrowErrors();
} catch (const std::string& e) {
HandleStringyException(e.c_str());
} catch (const char* e) {
HandleStringyException(e);
}
P.S. It should be mentioned that exceptions are better to be handled polymorphically, and in order to do so, the objects thrown should be chosen wisely. As mentioned by others, throwing objects like strings and pointers is a bad practice, and generally you'd like to throw objects derived from std::exception. Sometimes, however, the throwing code is not under your control and you have to make the best of it. I think that's a different discussion.
There is a simple solution to your actual problem:
Throw only std::string or only const char*.
Or even better throw something derived from std::exception
I have a very poor understanding of exception handling(i.e., how to customize throw, try, catch statements for my own purposes).
For example, I have defined a function as follows: int compare(int a, int b){...}
I'd like the function to throw an exception with some message when either a or b is negative.
How should I approach this in the definition of the function?
Simple:
#include <stdexcept>
int compare( int a, int b ) {
if ( a < 0 || b < 0 ) {
throw std::invalid_argument( "received negative value" );
}
}
The Standard Library comes with a nice collection of built-in exception objects you can throw. Keep in mind that you should always throw by value and catch by reference:
try {
compare( -1, 3 );
}
catch( const std::invalid_argument& e ) {
// do stuff with exception...
}
You can have multiple catch() statements after each try, so you can handle different exception types separately if you want.
You can also re-throw exceptions:
catch( const std::invalid_argument& e ) {
// do something
// let someone higher up the call stack handle it if they want
throw;
}
And to catch exceptions regardless of type:
catch( ... ) { };
Though this question is rather old and has already been answered, I just want to add a note on how to do proper exception handling in C++11:
Use std::nested_exception and std::throw_with_nested
It is described on StackOverflow here and here, how you can get a backtrace on your exceptions inside your code without need for a debugger or cumbersome logging, by simply writing a proper exception handler which will rethrow nested exceptions.
Since you can do this with any derived exception class, you can add a lot of information to such a backtrace!
You may also take a look at my MWE on GitHub, where a backtrace would look something like this:
Library API: Exception caught in function 'api_function'
Backtrace:
~/Git/mwe-cpp-exception/src/detail/Library.cpp:17 : library_function failed
~/Git/mwe-cpp-exception/src/detail/Library.cpp:13 : could not open file "nonexistent.txt"
Just add throw where needed, and try block to the caller that handles the error. By convention you should only throw things that derive from std::exception, so include <stdexcept> first.
int compare(int a, int b) {
if (a < 0 || b < 0) {
throw std::invalid_argument("a or b negative");
}
}
void foo() {
try {
compare(-1, 0);
} catch (const std::invalid_argument& e) {
// ...
}
}
Also, look into Boost.Exception.
You could define a message to throw when a certain error occurs:
throw std::invalid_argument( "received negative value" );
or you could define it like this:
std::runtime_error greatScott("Great Scott!");
double getEnergySync(int year) {
if (year == 1955 || year == 1885) throw greatScott;
return 1.21e9;
}
Typically, you would have a try ... catch block like this:
try {
// do something that causes an exception
}catch (std::exception& e){ std::cerr << "exception: " << e.what() << std::endl; }
Adding to this answer, as it doesn't seem advantageous to create another answer for this Q&A at this time.
In the case where you create your own custom exception, that derives from std::exception, when you catch "all possible" exceptions types, you should always start the catch clauses with the "most derived" exception type that may be caught. See the example (of what NOT to do):
#include <iostream>
#include <string>
using namespace std;
class MyException : public exception
{
public:
MyException(const string& msg) : m_msg(msg)
{
cout << "MyException::MyException - set m_msg to:" << m_msg << endl;
}
~MyException()
{
cout << "MyException::~MyException" << endl;
}
virtual const char* what() const throw ()
{
cout << "MyException::what" << endl;
return m_msg.c_str();
}
const string m_msg;
};
void throwDerivedException()
{
cout << "throwDerivedException - thrown a derived exception" << endl;
string execptionMessage("MyException thrown");
throw (MyException(execptionMessage));
}
void illustrateDerivedExceptionCatch()
{
cout << "illustrateDerivedExceptionsCatch - start" << endl;
try
{
throwDerivedException();
}
catch (const exception& e)
{
cout << "illustrateDerivedExceptionsCatch - caught an std::exception, e.what:" << e.what() << endl;
// some additional code due to the fact that std::exception was thrown...
}
catch(const MyException& e)
{
cout << "illustrateDerivedExceptionsCatch - caught an MyException, e.what::" << e.what() << endl;
// some additional code due to the fact that MyException was thrown...
}
cout << "illustrateDerivedExceptionsCatch - end" << endl;
}
int main(int argc, char** argv)
{
cout << "main - start" << endl;
illustrateDerivedExceptionCatch();
cout << "main - end" << endl;
return 0;
}
NOTE:
The proper order should be vice-versa, i.e.- first you catch (const MyException& e) which is followed by catch (const std::exception& e).
As you can see, when you run the program as is, the first catch clause will be executed (which is probably what you did NOT want in the first place).
Even though the type caught in the first catch clause is of type std::exception, the "proper" version of what() will be called - cause it is caught by reference (change at least the caught argument std::exception type to be by value - and you will experience the "object slicing" phenomena in action).
In case that the "some code due to the fact that XXX exception was thrown..." does important stuff WITH RESPECT to the exception type, there is misbehavior of your code here.
This is also relevant if the caught objects were "normal" object like: class Base{}; and class Derived : public Base {}...
g++ 7.3.0 on Ubuntu 18.04.1 produces a warning that indicates the mentioned issue:
In function ‘void illustrateDerivedExceptionCatch()’:
item12Linux.cpp:48:2: warning: exception of type ‘MyException’ will be caught
catch(const MyException& e)
^~~~~
item12Linux.cpp:43:2: warning: by earlier handler for ‘std::exception’
catch (const exception& e)
^~~~~
Again, I will say, that this answer is only to ADD to the other answers described here (I thought this point is worth mentioning, yet could not depict it within a comment).