I know that in C++ you can catch an exception of any data type using:
try {
// throw exception here
} catch (...) {
// handle exception here
}
But I want to catch any C++ standard exception, such as std::logic_error, std::out_of_range, and not ones of other data types such as string or int. How can I catch only the C++ standard exceptions only? I want to call exp.what() on the passed in C++ standard exception object, and that's not possible using the above code.
All standard exceptions derive from std::exception, so catch that instead:
try {
// throw exception here
}
catch (const std::exception &e) {
// handle exception here
}
Related
I have a try-catch block like below
try
{
// Do something here.
}
catch (const std::exception &e)
{
// std exception.
}
catch(...)
{
// Unknown exception. We can't know the type.
}
I am reading some documentation from http://www.cplusplus.com/reference/exception/exception/ but to me it is not obvious how to know what exception type was caught when the code goes into the std::exception part.
Is there a way to get a string with the type of error? (I don't want to surface the error message, just the exception type)
Is there a way to get a string with the type of error?
Sort of. If you catch by reference (as you are doing in the above code), then you can apply typeid to the exception to get some info about its dynamic type. This is made possible by the fact that std::exception is a polymorphic type. However, there's no guarantee that std::type_info::name() is a readable name for the type.
You can catch different exceptions with different catch blocks:
try
{
// Do something here.
}
catch (const std::runtime_error& e)
{
// Handle runtime error
}
catch (const std::out_of_range& e)
{
// Handle out of range
}
catch (const std::exception &e)
{
// Handle all other exceptions
}
catch(...)
{
// Unknown exception. We can't know the type.
}
Of course it does not always make sense to have a seperate catch for every type of exception, so you still would need a way to tell what is the type of the exception within the catch(std::exception&) block, for which I refer you to this answer.
I've been learning about the try-catch block in C++ and I don't understand the syntax of the catch function. On cppreference, it says the following:
1) To declare a formal parameter in the catch clause:
catch (const std::exception& e) { /* */ }
2) To declare an unnamed parameter:
catch (const std::exception&) { /* */ }
3) To write a "catch-all handler" (not sure what this means), which is activated for any exception:
catch (...) { /* */ }
Questions:
1) What is the difference between these catch blocks? I'm not sure how a formal parameter, unnamed parameter, and a "catch-all handler" differ.
2) What type is the parameter e of the catch clause? Is it of type exception? I've never seen this type used other than in examples on how to write a try-catch block. If so, how could I use it in a catch clause to, let's say, output an error message? Can e accept a string I've sent in when I throw an error?
3) I've experimented and written a try-catch block as follows:
#include <iostream>
#include <string>
#include <stdexcept>
try
{
throw invalid_argument("Error, program stopped.");
}
catch(const string& e)
{
cout << e;
}
This code successfully calls the catch block and prints my message: "Error, program stopped.". However, the .exe suddenly stops working and crashes. I don't know if this is normal when an exception is thrown, or if my code is bad.
catch (const std::exception& e) { /* */ }
You need to use a named exception if you want to be able to access the exception object in the catch block. For example if you wanted to print e.what().
catch (const std::exception&) { /* */ }
You can use an un-named exception if you don't need to access the exception object. Maybe you don't care about the contents of the exception, and you just want to handle all exceptions (of this type) in the same way.
catch (...) { /* */ }
C++ allows you to throw an object of any type, whether or not it is of a type derived from std::exception. This type of catch block will catch anything thrown. Just like the un-named exception, you will not have access to the thrown object. But also, you won't even have any way to know what type it is.
For your final example, I don't think it is your catch block that is printing the message. After all, you're catching the wrong type. Some compilers will automatically insert exception catching code that will catch anything that escapes main, and if it is a type derived from std::exception, it will print the result of what(), before terminating the program. I believe GCC does this, but Visual Studio does not. Not sure about Clang or any other compilers.
I know that you can catch "all exceptions" and print the exception by
try
{
//some code...
}catch(const std::exception& e) {
cout << e.what();
}
but this is just for exceptions derived from std::exception.
I was wondering if there is a way to get some information from an ellipsis catch
try
{
//some code...
}catch(...) {
// ??
}
If the mechanism is the same as ellipsis for functions then I should be able to do something like casting the argument of the va_list and trying to call the what() method.
I haven't tried it yet but if someone knows the way I'd be excited to know how.
From C++11 and onwards, you can use std::current_exception &c:
std::exception_ptr p;
try {
} catch(...) {
p = std::current_exception();
}
You can then "inspect" p by taking casts &c.
In earlier standards there is no portable way of inspecting the exception at a catch(...) site.
Sorry, you can't do that. You can only access the exception object in a catch block for a specific exception type.
I have searched a lot for the differences between these two types of handlers, but everyone said that catch(...) is a generic handler which catches everything.
I could not find any exception that one of them can handle and the other cannot. Even divide by zero, creates an exception that both of them cannot handle (floating point exception).
Can anyone give me a sample and explain clearly their difference? Which one of them should I use?
Is there any exception that catch(...) can handle while catch(exception& ex) cannot?
Yes, any exception that is not, or not derived from, std::exception will not be caught by catch(exception&). For example; throw 42; will be caught by catch(...), but not catch(exception&).
A throw exception(); can be caught by either; the first handler is chosen. The catch(...) should be the last handler.
Even divide by zero, creates an exception which both of them cannot handle (floating point exception)...
Visual Studio has two modes of exception handling; synchronous (/EHsc) and asynchronous (/EHa). For the synchronous handling, both catch(...) and catch(exception&) will only catch C++ exceptions; i.e. those thrown with a throw xyz;. For the asynchronous handling, access violations etc. can be caught with catch(...).
VS also offers a function _set_se_translator() that can be used to "translate" or handle the Win32 exceptions. Typically the function is used to translate the Win32 exception to a C++ exception (derived from exception) that can be handled by a catch(exception&).
A sample of what the translation could look like (some detail is omitted for brevity);
struct seh_exception : std::runtime_error {
//...
};
struct access_violation : seh_exception {
//...
};
struct unspecified_seh_exception : seh_exception {
//...
};
void translation_function(unsigned int code, ::EXCEPTION_POINTERS* info)
{
switch (code) {
case EXCEPTION_ACCESS_VIOLATION:
throw access_violation();
break;
// more cases for other exception codes
};
throw unspecified_seh_exception();
}
Which one of them should I use?
You should use the one that you can do something with. If all exceptions result in the same handling by your code, then use catch(...). If your code needs to handle the exceptions separately, then you should have a handler for each exception that is expected.
Sure, any exception that is of a type that doesn't have std::exception as its base class will not be caught by catch(std::exception& ex).
For example,
struct foo {};
throw foo();
will be caught by catch (...), and not by std::exception.
You are allowed to throw pretty much anything (e.g an int), and catch(...) will catch anything. catch(exception&) will only catch exception or derived types.
catch(...){} is catching all exceptions. catch(std::exception& ex){} is catching all exceptions with std::exception as a base class.
http://en.cppreference.com/w/cpp/language/try_catch
Currently, I am investigating some code that uses the CFile class from the MFC Library to open a text file.
I found two kinds of error handling in the code: This are just sample since it is confidential to post the code.. Just think that the body of the try statement contains only member functions of CFile class.
1
try {
if(file.Open(strPath,Cfile::modeRead|CFile::shareDenyNone)){
file.Read(strKey, dataLength);
file.Close();
}
}
catch (CFileException& e) {
}
2
try {
// same code above
}
catch (CFileException *e) {
}
What is the difference between the two kinds of exception handling?
What are the possible errors that can be thrown by member functions of the CFile class?
Is no. 1 way possible for catching exceptions thrown by a member function of the CFile class?
You can throw exception objects in two ways, by value:
CException ex;
throw ex; // CException
or by pointer:
CException *ex = new CException();
throw ex; // CException *
When catching the exception, you catch the corresponding type of what has been thrown, that is, a pointer, or a value. To avoid a copy, we usually catch-by-value using a reference:
catch(CException &e) // when throwing CException
MFC throws exceptions by pointer; see https://msdn.microsoft.com/en-us/library/0e5twxsh.aspx
try {
AfxThrowUserException();
}
catch( CException* e ) {
e->Delete();
}
Don't forget do delete the exception afterwards, or you get a small memory leak each time an exception is thrown.