I have been learning c++ recently and while working on exceptions, I came across something that confuses me. I threw a string exception and added multiple catch blocks to see how it works, and for some reason, the string exception is being caught in the int catch block. This is puzzling me and I cant see to find reasons why it would do it.
FYI, I am using GCC v 5.3.0
So, I was expecting the following message on the console.
String exception occurred: Something else went wrong
But instead, I got the following message.
Int exception occurred: 14947880
So I tried switching the order of the catch blocks and placed the string catch block on the top, and I got the string exception message. Could somebody please explain a reason why this is happening? It seems whatever catch block is in the top is being caught first.
I don't think this is the correct behavior and that the string exception block should be executed, but if I am wrong, please correct me. Thanks for taking time to look at this.
#include <iostream>
using namespace std;
void MightGoWrong()
{
bool error = true;
if (error)
{
throw string("Something else went wrong");
}
}
/**
* Output on console: Int exception occurred: 14947880
*/
int main() {
try
{
MightGoWrong();
}
// If string or char pointer catch block goes to top, that block will execute
catch (int e)
{
cout << "Int exception occurred: " << e << endl;
}
catch (string &e)
{
cout << "String exception occurred: " << e << endl;
}
catch (char const * e)
{
cout << "Char exception occurred: " << e << endl;
}
return 0;
}
Related
I am a bit confused on where I should throw an exception and where I should catch it. Right now I am throwing an invalid_argument as soon as someone creates a book with an invalid page.
In my main function I am then creating a book with an invalid page and I am catching that exception and writing out the message. Is this how you are supposed to do it? Because right now I am only catching one single instance of a book. If I tried to create another book outside the try catch block with an invalid page I woudnt be able to catch it. Is this really necessary? Is this how I'm supposed to handle exceptions?
#include <iostream>
#include <string>
#include <stdexcept>
using namespace std;
class Book
{
public:
string title {};
string author {};
int pages {};
int readers {};
Book(string const& t, string const& a, int const p)
: title{t}, author{a}, pages{p}, readers{0}
{
if (pages <= 0)
throw invalid_argument ("Invalid page!");
}
void print() const
{
cout << "Title: " << title << "\nAuthor: " << author
<< "\nPages: " << pages << "\nReaders: " << readers << endl;
}
};
int main()
{
try
{
Book book_1("Harry Potter", "JK Rowling", 0);
}
catch(const exception& e)
{
cerr << "Exception: " << e.what() << endl;
}
//book_1.print();
return 0;
}
Yes, if you call a function that may throw an exception, at some point, you will need to handle it. The way to do it is to catch the exception.
Is it really necessary?
Well it depends. If in your case you ensure that you won't create your objects with invalid arguments, you don't need to catch an exception that'll never be raised.
Exception handling is only required when you don't know (you have no guarantee), for example when the page parameter is given from a user input, a file or anything that is unknown/not predictable/not controlled by the code base.
That being said, in your case you can do even better, just replace:
int pages;
with:
unsigned int pages;
And then it would not be possible to give an invalid number anymore. Which means you can completely remove the exception handling off your code.
The above proposal didn't take into account that 0 is considered invalid as well.
You should catch and handle the exception where it makes sense for the program.
First of all, your program always throws the exception independent of input, because the 0 is hard-coded. This doesn't seem to be a use case for an exception. This seems to be a logic error and so it should be considered a bug that needs fixing. Why should it make sense to try to create a guaranteed invalid book?
But let's suppose the number of pages is given by user input. Then the next issue would be that you can't print a book that failed to be created. So book_1.print(); must be part of the try block.
Let's suppose you have a second book book_2, also created from input from the user. You need to ask yourself then whether it makes sense for the program logic to continue creating and using the second book if creating the first one failed.
If failing to create the first book means that there is no point in continuing with the second book, then just put everything in one try block, e.g.:
try
{
Book book_1(/*...*/);
book_1.print();
Book book_2(/*...*/);
book_2.print();
}
catch(const exception& e)
{
cerr << "Exception: " << e.what() << endl;
}
When either of the book creations fail, the program will continue executing in the catch handler and then after it, skipping over the rest of the book creations and printing. But if book_1 didn't throw on construction, then it will be printed before book_2 is "checked".
Maybe you would want
try
{
Book book_1(/*...*/);
Book book_2(/*...*/);
book_1.print();
book_2.print();
}
catch(const exception& e)
{
cerr << "Exception: " << e.what() << endl;
}
With this the program will not print any book if creation of either book fails.
If it does make sense for the program to continue execution if creation of the first book failed, then use two try/catch statements to handle the errors individually:
try
{
Book book_1(/*...*/);
book_1.print();
}
catch(const exception& e)
{
cerr << "Exception: " << e.what() << endl;
}
try
{
Book book_2(/*...*/);
book_2.print();
}
catch(const exception& e)
{
cerr << "Exception: " << e.what() << endl;
}
You might want to consider using a function or arrays and loops to make this less redundant, for example if the goal is to just repeatedly take user input, create a book and then print it, a simple loop will be helpful:
while(true)
{
try
{
/* take user input here */
if(/* some exit condition */)
{
break;
}
Book book(/* arguments from user input */);
book.print();
}
catch(const exception& e)
{
cerr << "Exception: " << e.what() << endl;
}
}
This loop will run until the exit condition is satisfied. If any standard exception (from book creation or the input operation) is thrown, the exception message will be printed and the loop continues anew.
(As an additional note: In all of the examples above all exceptions inherited from std::exception thrown in the try blocks will be caught. This means not only the invalid_argument exception from the book creation, but e.g. any exception thrown by .print() or the input handling. You may not want to handle these the same way as the invalid book creation. For example an exception from input operations could mean that there is no way for the program to continue the loop. Therefore it makes sense to use a custom class (maybe inherited from std::invalid_argument) for the throw in Book's constructor and catch only that. This way you can handle the invalid book creation specifically.)
<C++>In exception handling, do you need to know what exception and where an exception is going to occur? Can you make a code which will print and notify us that an exception occurred somewhere in the program. I mean I have a program in which I don't know if an exception will occur or not, if one was to occur, then it will print to notify us.
Exception handling is something you should design for, and in fact it works very well together with RAII (https://en.cppreference.com/w/cpp/language/raii).
(Notr On embedded platforms using exceptions, is not so popular because of some runtime overhead). What I personally like about exceptions is that it separates error handling from the normal program flow (there will be hardly any if then else checks when done right)
// Exception handling should be part of your overal design.And many standard library functions can throw exceptions, It is always up to you where you handle them.
#include <iostream>
#include <string>
#include <stdexcept>
int get_int_with_local_exception_handling()
{
do
{
try
{
std::cout << "Input an integer (local exception handling, enter a text for exception): ";
std::string input;
std::cin >> input;
// stoi is a function that can throw exceptions
// look at the documentation https://en.cppreference.com/w/cpp/string/basic_string/stol
// and look for exceptions.
//
int value = std::stoi(input);
// if input was ok, no exception was thrown so we can return the value to the client.
return value;
}
// catch by const reference, it avoids copies of the exception
// and makes sure you cannot change the content
catch (const std::invalid_argument& e)
{
// std::exceptions always have a what function with readable info
std::cout << "handling std::invalid_argument, " << e.what() << "\n";
}
catch (const std::out_of_range& e)
{
std::cout << "handling std::out_of_range, " << e.what() << "\n";
}
} while (true);
}
int get_int_no_exception_handling()
{
std::cout << "Input an integer (without exception handling, enter a text for exception): ";
std::string input;
std::cin >> input;
int value = std::stoi(input);
return value;
}
int main()
{
try
{
// this function shows you can handle exceptions locally
// to keep program running
auto value1 = get_int_with_local_exception_handling();
std::cout << "your for input was : " << value1 << "\n";
// this function shows that exceptions can be thrown without
// catching, but then the end up on the next exception handler
// on the stack, which in this case is the one in main
auto value2 = get_int_no_exception_handling();
std::cout << "your input was : " << value1 << "\n";
return 0;
}
catch (const std::exception& e)
{
std::cout << "Unhandled exception caught, program terminating : " << e.what() << "\n";
return -1;
}
catch (...)
{
std::cout << "Unknown, and unhandled exception caught, program terminating\n";
}
}
Yes and no.
No, because any exception thrown via throw some_exception; can be catched via catch(...).
Yes, because catch(...) is not very useful. You only know that there was an excpetion but not more.
Typically exceptions carry information on the cause that you want to use in the catch. Only as a last resort or when you need to make abolutely sure not to miss any excpetion you should use catch(...):
try {
might_throw_unknown_exceptions();
} catch(std::exception& err) {
std::cout << "there was a runtime error: " << err.what();
} catch(...) {
std::cout << "an unknown excpetion was thrown.";
}
The C++ standard library uses inheritance only sparingly. Exceptions is only place where it is used extensively: All standard exceptions inherit from std::exception and it is good practice to inherit also custom exceptions from it.
else
{
// figure out how to fo out of range excetpion.
throw std::out_of_range("An exception occurred: Grade must be between 0.000000 and 100.000000");
//throw std::out_of_range("Grade points must be between 0.000000 and 100.000000.");
}
I get the error:
Percentage grade: 10000
terminate called after throwing an instance of 'std::out_of_range'
what(): An exception occurred: Grade must be between 0.000000 and 100.000000"
How do I remove this?:
terminate called after throwing an instance of'std::out_of_range'
what():"
You can remove this:
terminate called after throwing an instance of'std::out_of_range'
what():"
By using similar code as explained below:
int x = 10;
int y = 0;
int z = 0;
try {
if (y == 0) throw ("Something wrong going on!"); // throwing string as error
z = x / y;
std::cout << z << std::endl;
} catch (const char *m) {
std::cerr << m << std::endl; // printing error
}
You get something like:
Something wrong going on!
message. When you use a class like std::out_of_range, it'll show the information about where it actually thrown from during program execution. You can suppress it by not using the functions and directly use strings in throw statements and don't forget to catch the string for exception.
When you throw, you need to catch...
#include <iostream>
#include <exception>
using namespace std;
struct OORException : public exception {
const char* what () const throw () {
return "Exception out of range: Grade must be between 0.000000 and 100.000000";
}
};
int main () {
// Use an application defined exception
try
{
// value out of range exception.
throw OORException();
// throw std::out_of_range("An exception occurred: Grade must be between 0.000000 and 100.000000");
//throw std::out_of_range("Grade points must be between 0.000000 and 100.000000.");
}
catch(OORException& e) {
std::cout << "OORException caught" << std::endl;
std::cout << e.what() << std::endl;
}
// use a predefined std::exception
try
{
// value out of range exception.
throw std::out_of_range("Exception occurred: Grade must be between 0.000000 and 100.000000");
}
catch (std::out_of_range& e)
{
std::cout << "Exception Out Of Range " << e.what() << std::endl;
}
catch (std::exception& e)
{
std::cout << "An exception occurred. Exception " << e.what() << std::endl;
}
return 0;
}
Whether you should throw/catch in this case is a different question.
throw'ing the std::out_of_range exception is not a problem, in of itself. The real problem is that std::terminate() is called automatically to kill the calling process if a thread throws an exception and does not catch it.
So, you need to call your throwing function inside of a try block and catch the exception.
Hi I am very new to C++ programming, and I am really hard to understand the code below in which they have used catch. So I want to know why do they use catch in this code. Thanks in advance
#include <iostream>
#include <exception>
using namespace std;
int main ()
{
try
{
int* myarray = new int[1000];
cout << "allocated";
}
catch (exception& e)
{
cout << "Standard exception: " << e.what() << endl;
}
return 0;
}
The operator new may throw an exception in case it cannot allocate the required space.
From the link above:
throwing (1) void* operator new (std::size_t size) throw (std::bad_alloc);
Throws bad_alloc if it fails to allocate storage. Otherwise, it throws
no exceptions (no-throw guarantee).
The statements in catch will be executed when one of the statements in the try block throws an exception. This tutorial link will helps a ton: http://www.cplusplus.com/doc/tutorial/exceptions/
try and catch come inside exception handling in C++
try
{
int* myarray = new int[1000];
cout << "allocated";
}
catch (exception& e)
{
cout << "Standard exception: " << e.what() << endl;
}
in this case first it wil check the memory allocation using try block and if it fail to allocate the memory then using catch it will throw exception,that memory could not be allocated
Is there some way to catch exceptions which are otherwise unhandled (including those thrown outside the catch block)?
I'm not really concerned about all the normal cleanup stuff done with exceptions, just that I can catch it, write it to log/notify the user and exit the program, since the exceptions in these casese are generaly fatal, unrecoverable errors.
something like:
global_catch()
{
MessageBox(NULL,L"Fatal Error", L"A fatal error has occured. Sorry for any inconvience", MB_ICONERROR);
exit(-1);
}
global_catch(Exception *except)
{
MessageBox(NULL,L"Fatal Error", except->ToString(), MB_ICONERROR);
exit(-1);
}
This can be used to catch unexpected exceptions.
catch (...)
{
std::cout << "OMG! an unexpected exception has been caught" << std::endl;
}
Without a try catch block, I don't think you can catch exceptions, so structure your program so the exception thowing code is under the control of a try/catch.
Check out std::set_terminate()
Edit: Here's a full-fledged example with exception matching:
#include <iostream>
#include <exception>
#include <stdexcept>
struct FooException: std::runtime_error {
FooException(const std::string& what): std::runtime_error(what) {}
};
int main() {
std::set_terminate([]() {
try {
std::rethrow_exception(std::current_exception());
} catch (const FooException& e) {
std::cerr << "Unhandled FooException: " << e.what() << std::endl;
} catch (const std::exception& e) {
std::cerr << "Unhandled exception: " << e.what() << std::endl;
} catch (...) {
std::cerr << "Unhandled exception of unknown type" << std::endl;
}
std::abort();
});
throw FooException("Bad things have happened.");
// throw std::runtime_error("Bad things have happened.");
// throw 9001;
}
You can use SetUnhandledExceptionFilter on Windows, which will catch all unhandled SEH exceptions.
Generally this will be sufficient for all your problems as IIRC all the C++ exceptions are implemented as SEH.
Without any catch block, you won't catch any exceptions. You can have a catch(...) block in your main() (and its equivalent in each additional thread). In this catch block you can recover the exception details and you can do something about them, like logging and exit.
However, there are also downside about a general catch(...) block: the system finds that the exception has been handled by you, so it does not give any more help. On Unix/Linux, this help would constitute creating a CORE file, which you could load into the debugger and see the original location of the unexcepted exception. If you are handling it with catch(...) this information would be already lost.
On Windows, there are no CORE files, so I would suggest to have the catch(...) block. From that block, you would typically call a function to resurrect the actual exception:
std::string ResurrectException()
try {
throw;
} catch (const std::exception& e) {
return e.what();
} catch (your_custom_exception_type& e) {
return e.ToString();
} catch(...) {
return "Ünknown exception!";
}
}
int main() {
try {
// your code here
} catch(...) {
std::string message = ResurrectException();
std::cerr << "Fatal exception: " << message << "\n";
}
}
Update: This covers c++98 only.
From More Effective C++ by Meyers (pg 76), you could define a function that gets called when a function generates an exception that is not defined by its exception specification.
void convertUnexpected()
{
// You could redefine the exception here into a known exception
// throw UnexpectedException();
// ... or I suppose you could log an error and exit.
}
In your application register the function:
std::set_unexpected( convertUnexpected );
Your function convertUnexpected() will get called if a function generates an exception that is not defined by its exception specification... which means this only works if you are using exception specifications. ;(
Provided that C++11 is available, this approach may be used (see example from: http://en.cppreference.com/w/cpp/error/rethrow_exception):
#include <iostream>
#include <exception>
void onterminate() {
try {
auto unknown = std::current_exception();
if (unknown) {
std::rethrow_exception(unknown);
} else {
std::cerr << "normal termination" << std::endl;
}
} catch (const std::exception& e) { // for proper `std::` exceptions
std::cerr << "unexpected exception: " << e.what() << std::endl;
} catch (...) { // last resort for things like `throw 1;`
std::cerr << "unknown exception" << std::endl;
}
}
int main () {
std::set_terminate(onterminate); // set custom terminate handler
// code which may throw...
return 0;
}
This approach also allows you to customize console output for unhandled exceptions: to have something like this
unexpected exception: wrong input parameters
Aborted
instead of this:
terminate called after throwing an instance of 'std::logic_error'
what(): wrong input parameters
Aborted
This is what I always do in main()
int main()
{
try
{
// Do Work
}
catch(std::exception const& e)
{
Log(e.what());
// If you are feeling mad (not in main) you could rethrow!
}
catch(...)
{
Log("UNKNOWN EXCEPTION");
// If you are feeling mad (not in main) you could rethrow!
}
}
Use catch (...) in all of your exception barriers (not just the main thread). I suggest that you always rethrow (...) and redirect standard output/error to the log file, as you can't do meaningful RTTI on (...). OTOH, compiler like GCC will output a fairly detailed description about the unhandled exception: the type, the value of what() etc.