std::system_error handles exception with associated error code. Is it possible using common catch block to get std::system_error exception message and it's code? Like this
try{
// code generating exception
} catch (const std::exception& ex){ // catch all std::exception based exceptions
logger.log() << ex.what(); // get message and error code
// if exception type is system_error
}
Is the only way is to catch directly std::system_error type and get its code before base exception type catching? What is the best approach to use std::system_error widely?
What is the best approach to use std::system_error widely?
The best approach in my opinion, is to catch the exception directly.
catch (const std::system_error& e) {
std::cout << e.what() << '\n';
std::cout << e.code() << '\n';
} catch (const std::exception& e) {
std::cout << e.what() << '\n';
}
Is the only way is to catch directly std::system_error type and get its code before base exception type catching?
It's technically not the only way. It's the obvious and idiomatic way. You can use dynamic_cast.
catch (const std::exception& e) {
std::cout << e.what() << '\n';
auto se = dynamic_cast<const std::system_error*>(&e);
if(se != nullptr)
std::cout << se->code() << '\n';
}
But you mention in the comment that you prefer not to use dynamic_cast. It's possible to avoid that too, but not in any way that has any advantages.
Note that even if you can do things in non obvious ways, it doesn't mean that you should.
Related
Try/catch block in C++ not being "caught."
I'm trying to have one catch block to get all exceptions.
#include <iostream>
#include <exception>
using namespace std;
int main()
{
try
{
throw 1;
}
catch (exception& e)
{
cout << "ERROR: " << e.what() << endl;
return 1;
}
return 0;
}
throw 1; will throw an int. As you do not catch an int, the exception goes uncaught, which is undefined behavior. Though it is possible to throw anything, always prefer to throw a class that derives from std::exception. You can catch an int with catch(int e) or catch(...), but there's really no reason to ever do that.
If you catch with catch(...), then you do not know the type of the object, so cannot access any members, properties, or other aspects, and so you cannot* gather any information about what was thrown. This should never be used.
*There are ways to get information about the thrown object, but it's far easier to just catch the right type in the first place
You are throwing an int, but only catching std::exception. Use a catch(...) to catch everything thrown.
I know the difference in handling of both of these catches, but what does it take for the ellipse to catch something the std::exception catch wouldn't catch?
For example:
try
{
throw std::runtime("runtime error!");
}
catch(const std::exception& e)
{
std::cout << "Exception: " << e;
}
catch(...)
{
std::cout << "How did I get here?";
throw;
}
I've seen examples of code that use both of these in conjunction, but I've not seen a reason you would do both.
catch(const std::exception& e)
Will catch std exceptions only.
catch(...)
Will catch everything there after.
You can handle integers and other types (http://www.cplusplus.com/doc/tutorial/exceptions/)
For example:
catch(int e)
While it's definitely a good idea to do so, you don't have to derive your custom exceptions from std::exception. C++ allows you to throw practically any object type.
So throw 1; will not be handled by your first handler, for example. And neither will...
class MyCustomException { // Doesn't derive
///
};
... if it was thrown.
You probably meant:
throw std::runtime_error("runtime error!"); // not std::runtime
The std::runtime_error is derived from the std::exception so your first catch block is fired up as it catches exceptions of type std::exception. And there you probably meant:
std::cout << "Exception: " << e.what(); // not e
If you threw anything else other than the std::run_time or std::exception and its derivatives, the second catch block would be triggered. Useful reading from the C++ FAQ:
What should I throw?
As written, the throw statement throws an object whose type is derived from std::exception, so it's caught by the first catch clause. If you change the throw to throw 3; the exception will be caught by the second catch clause, not the first.
I'm compiling the following code with Visual C++ 2017 (C++17 features are enabled)
int main() {
try {
// loot is some library that is linked as a dll
auto game = loot::CreateGameHandle(loot::GameType::fonv, "c:\\something\\invalid", "C:\\something\\invalid");
// throw std::invalid_argument("this works as expected");
}
catch (const std::exception &e) {
std::cout << "caught as exception " << e.what() << std::endl;
}
catch (const std::invalid_argument &e) {
std::cout << "caught as invalid_argument " << e.what() << std::endl;
}
catch (...) {
std::cout << "caught by ..." << std::endl;
}
}
The compiler reports, as expected:
warning C4286: 'const std::invalid_argument &': is caught by base class ('const stdext::exception &') on line 8
However, the application output is
caught as invalid_argument Given game path "c:\something\invalid" does not resolve to a valid directory.
And it's not just changing the catch order or something, if I remove the last 2 catch blocks, the application crashes because of the unhandled exception.
How is that even possible? I'm assuming this is somehow related to compiler settings that make my std::exception be a different type from the one std::invalid_argument inside the library inherits from - but why then is my std::invalid_argument the same type as theirs?
Is there a way to fix this? Because that library throws a lot of different exception types and I can't really catch each one individually.
Bloody hell, sorry for this.
It turns out the build system I was using added _HAS_EXCEPTIONS=0 to the preprocessor definitions. That's what's causing this.
This question already has answers here:
An exception gets thrown twice from a constructor with a function-try-block
(3 answers)
Closed 8 years ago.
I am new to C++ exception handling. The rule in my mind is that,
If no handler of an exception is found in the call chain (the stack of function calling), then the terminate function is called.
A handler is a catch {} block.
However, I cannot understand the behaviour of the following.
#include <iostream>
#include <exception>
using namespace std;
struct X {
X() try { throw exception(); }
catch (exception &e) {
cout << "Exception caught in constructor!" << endl;
}
};
int main() {
try {
throw exception();
}
catch (exception &e) {
cout << "Exception caught in function." << endl;
}
cout << "After Exception being caught in function" << endl;
try {
X x;
}
catch (exception &e) {
cout << "Why exception is caught again!" << endl;
}
return 0;
}
The output is
Exception caught in function.
After Exception being caught in function
Exception caught in constructor!
Why exception is caught again!
Question 1: It seems that the exception thrown in the constructor of X is caught (or. handled) twice. Or why the catch{} block following the constructor not counted as a handler for the exception in the constructor?
If I do not put X x; in the try{} block and catch it in the main(), the output is:
Exception caught in function.
After Exception being caught in function
Exception caught in constructor!
terminate called after throwing an instance of 'std::exception'
what(): std::exception
Aborted (core dumped)
Question 2: Is the default terminate() function called when we do not have X x; in a try block?
With:
X() try { throw exception(); }
catch (exception &e) {
cout << "Exception caught in constructor!" << endl;
}
X object is not completely constructed and so the catch cannot ignore the exception and should re-throw it.
IMO, it is more clear when X has a member which throw... (X() try : member(0) {} catch(exception&) {} ).
Note that you may use a normal try catch inside the constructor block:
X() {
try { throw exception(); }
catch (exception &e) {
cout << "Exception caught in constructor!" << endl;
}
}
which is more natural.
You have two exceptions.
struct X {
X() try { throw exception(); }
catch (exception &e) {
cout << "Exception caught in constructor!" << endl;
}
};
After an exception you will handle it in the constructor. BUT you didn't construct
the object yet and you have no object in the caller's side. The caller
should handle an un-constructed object situation. †
Second question, yes. Per [except.terminate] in the standard. It causes to invoke std::terminate.
This question already has answers here:
C++ get description of an exception caught in catch(...) block
(6 answers)
Closed 6 years ago.
If I want to write useful info to a file whenever i caught a catch-all exception, how to do it?
try
{
//call dll from other company
}
catch(...)
{
//how to write info to file here???????
}
You can't get any information out of the ... catch block. That is why code usually handles exceptions like this:
try
{
// do stuff that may throw or fail
}
catch(const std::runtime_error& re)
{
// speciffic handling for runtime_error
std::cerr << "Runtime error: " << re.what() << std::endl;
}
catch(const std::exception& ex)
{
// speciffic handling for all exceptions extending std::exception, except
// std::runtime_error which is handled explicitly
std::cerr << "Error occurred: " << ex.what() << std::endl;
}
catch(...)
{
// catch any other errors (that we have no information about)
std::cerr << "Unknown failure occurred. Possible memory corruption" << std::endl;
}
A caught exception is accessible by the function std::current_exception(), which is defined in <exception>. This was introduced in C++11.
std::exception_ptr current_exception();
However, std::exception_ptr is an implementation-defined type, so you can't get to the details anyway. typeid(current_exception()).name() tells you exception_ptr, not the contained exception. So about the only thing you can do with it is std::rethrow_exception(). (This functions seems to be there to standardize catch-pass-and-rethrow across threads.)
There's no way to know anything about the specific exception in a catch-all handler. It's best if you can catch on a base class exception, such as std::exception, if at all possible.
You can't get any details. The whole point of catch(...) is to have such "I don't know what can happen, so catch whatever is thrown". You usually place catch(...) after catch'es for known exception types.
I think he wants to make it log that an error occurred, but doesn't specifically need the exact error (he would write his own error text in that case).
The link DumbCoder posted above has at tutorial that will help you get what you're trying to achieve.