Reputation: 2062
Problem : I am using both std::exception and std::bad_alloc to catch exception. Something is wrong with the order of the try catch that I am using. I attached sample code for reference.
Expected : If my error is bad_alloc then the bad_alloc exception is thrown.
Observed : My error is bad_alloc, but exception is thrown.
Sample Code :
#include "stdafx.h"
#include <iostream>
#include <exception>
using namespace std;
void goesWrong()
{
bool error1Detected = true;
bool error2Detected = false;
if (error1Detected)
{
throw bad_alloc();
}
if (error2Detected)
{
throw exception();
}
}
int main()
{
try
{
goesWrong();
}
catch (exception &e)
{
cout << "Catching exception: " << e.what() << endl;
}
catch (bad_alloc &e)
{
cout << "Catching bad_alloc: " << e.what() << endl;
}
return 0;
}
Upvotes: 13
Views: 2830
Reputation: 19
In C++, the order in which exception handlers are listed is taken into account when matching handlers to exceptions. The first handler which can handle the exception will be called, even if there is a better match further down the list. This is different from Java or C#, where only the best match will be called (and the compiler forces you to put it at the top of the list).
As the exception is passed by reference, polymorphism applies; this means that a subclass can be passed to a handler that expects its parent class. Since std::bad_alloc is a subclass of std::exception, it will be handled by the first catch block.
To get the behaviour you expected, put the catch blocks the other way round:
catch (bad_alloc &e)
{
cout << "Catching bad_alloc: " << e.what() << endl;
}
catch (exception &e)
{
cout << "Catching exception: " << e.what() << endl;
}
This way round, std::bad_alloc will match the first handler, while std::exception and all its other subclasses will match the second.
Upvotes: 0
Reputation: 12212
You have to put your exceptions in reverse order, regarding their inheritance relationship. std::exception is the parent class of std::bad_alloc, that is why it is found before in the catch list. So you have to transform your code to be:
try {
goesWrong();
}
catch (bad_alloc &e)
{
cout << "Catching bad_alloc: " << e.what() << endl;
}
catch (exception &e)
{
cout << "Catching exception: " << e.what() << endl;
}
You're not limited to catch objects: you can throw integers, chars... whatever. In that case, catch(...)
is the only secure way to catch them all.
That said, using objects from the standard class library is the advised way to do it. And in this case, since std::exception is the base class for all (standard) exceptions, it will catch all possible exceptions thrown.
You can create your own exception classes deriving them from std::exception, or from std::runtime_error, for example, my personal choice.
Hope this helps.
Upvotes: 24