Run common code in case of any exception occurred in c++ - c++

I was looking similar to finally for c++ but I came across RAII. I have a small confusion though. If I have some common code I want to run in case of any exception,
Example: std::cout << "exception occured" << std::endl;
Is there a way to do that instead of copy the same code?
#include <iostream>
int main()
{
bool firstException = false;
try
{
if(firstException)
throw std::invalid_argument("the truth is out there!!");
else
throw std::domain_error("Bazzinga");
}
catch (std::invalid_argument const& e)
{
std::cout << e.what() << std::endl;
std::cout << "exception occured" << std::endl;
}
catch (std::domain_error const& e)
{
std::cout << e.what() << std::endl;
std::cout << "exception occured" << std::endl;
}
}

I got now what molbdnilo was talking about in the comment.
The code below has the answer. :) :D
#include <iostream>
int main()
{
bool firstException = true;
try
{
if(firstException)
throw std::invalid_argument("the truth is out there!!");
else
throw std::invalid_argument("Bazzinga");
}
catch (std::exception const& e)
{
std::cout << e.what() << std::endl;
std::cout << "exception occured" << std::endl;
}
}

Related

How to create single error handler for multiple catch that are just doing same thing at multiple place and add that error handler inside another file?

I don't have much knowledge of exception.
I have two files task.cpp, main.cpp. Inside task.cpp file, I have a lot try/catch statements. I want to remove all the generic handlers for things like ..., std::exception etc., they are just printing the error, and I want to create just a single error handler of this kind and reside it inside main.cpp. How can I do it ?
These are some part of task.cpp & main.cpp file.
I want to remove catch (...) , catch (Exception const& _exception) from task.cpp file as they are used at multiple steps and create repetitive code
try
{
if (!stack.parseAndAnalyze(src.first, src.second))
successful = false;
else
stack.optimize();
}
catch (Exception const& _exception)
{
serr() << "Exception in assembler: " << boost::diagnostic_information(_exception) << endl;
return false;
}
catch (std::exception const& _e)
{
serr() <<
"Unknown exception during compilation" <<
(_e.what() ? ": " + string(_e.what()) : ".") <<
endl;
return false;
}
catch (...)
{
serr() << "Unknown exception in assembler." << endl;
return false;
}
}
if (_language != yul::AssemblyStack::Language::Ewasm && _targetMachine == yul::AssemblyStack::Machine::Ewasm)
{
try
{
stack.translate(yul::AssemblyStack::Language::Ewasm);
stack.optimize();
}
catch (Exception const& _exception)
{
serr() << "Exception in assembler: " << boost::diagnostic_information(_exception) << endl;
return false;
}
catch (std::exception const& _e)
{
serr() <<
"Unknown exception during compilation" <<
(_e.what() ? ": " + string(_e.what()) : ".") <<
endl;
return false;
}
catch (...)
{
serr() << "Unknown exception in assembler." << endl;
return false;
}
sout() << endl << "==========================" << endl;
sout() << endl << "Translated source:" << endl;
sout() << stack.print() << endl;
}
try
{
object = stack.assemble(_targetMachine);
object.bytecode->link(m_options.linker.libraries);
}
catch (Exception const& _exception)
{
serr() << "Exception while assembling: " << boost::diagnostic_information(_exception) << endl;
return false;
}
catch (std::exception const& _e)
{
serr() << "Unknown exception during compilation" << (
_e.what() ? ": " + string(_e.what()) : "."
) << endl;
return false;
}
catch (...)
{
serr() << "Unknown exception while assembling." << endl;
return false;
}
And catch inside main.cpp file like this:
int main(int argc, char** argv)
{
try
{
setDefaultOrCLocale();
solidity::frontend::CommandLineInterface cli(cin, cout, cerr);
if (!cli.parseArguments(argc, argv) || !cli.readInputFiles() || !cli.processInput() || !cli.actOnInput())
return 1;
return 0;
}
catch (boost::exception const& _exception || Exception const& _exception || InternalCompilerError const& _exception
|| smtutil::SMTLogicError const& _exception)
{
cerr << "Uncaught exception" << boost::diagnostic_information(_exception) << endl;
return 1;
}
catch (std::exception const& _e)
{
cerr() << "Uncaught exception" << (_e.what() ? ": " + string(_e.what()) : ".") << endl;
return 1;
}
catch (Exception const& _exc)
{
cerr() << string("Failed to import AST: ") << _exc.what() << endl;
return 1;
}
catch (...)
{
cerr << "Uncaught exception" << endl;
return 1;
}
}

std::nested_exception and polymorphism - Is this the best that can be done?

std::nested_exceptions are nice when all you want to do is calling what(), but accessing the interface of other exception types gets ugly.
Let us suppose I have two exception classes which store some additional information:
/* CODE BLOCK 1 */
class ErrorI : public std::runtime_error {
public:
ErrorI(int a_integer) : std::runtime_error{"ErrorI"}, integer{a_integer} {}
int integer;
};
class ErrorD : public std::runtime_error {
public:
ErrorD(double a_real) : std::runtime_error{"ErrorD"}, real{a_real} {}
double real;
};
Without nested exceptions, we can access the member variables in the try/catch block:
/* CODE BLOCK 2 */
int main()
{
try {
/* do stuff */;
}
catch(const ErrorI& ee){
std::cout << " Value: " << ee.integer << std::endl;
}
catch(const ErrorD& ee){
std::cout << " Value: " << ee.real << std::endl;
}
}
But if we want to unwrap a std::nested_exception, things are not so straightforward. We need to define a function which will be called recursively, which should look like this:
/* CODE BLOCK 3 */
void process_exception(const std::exception& e, int level=0) {
try {
std::rethrow_if_nested(e);
}
catch(const std::exception& e) {
process_exception(e, level+1);
}
/* ... process the top-most (latest) exception ... */
}
Unfortunately, for processing the top-most exception, we cannot use the try/catch syntax in Code Block 2: if we rethrow e, it will be truncated to an std::exception, and we will lose all the additional information. EDIT: This is not true if std::rethrow_exception and std::exception_ptr are used.
So we're back to the problem of good-ole dynamic type-checking, with all that it entails (see this for example).
Derive all the exceptions from a common base class with the desired interface. This includes approaches like the Visitor pattern. This is neat, but not good if the exception classes are provided by a external library.
Using dynamic_cast:
/* CODE BLOCK 4 */
if (auto p = dynamic_cast<ErrorI const*>(&e)) {
std::cout << " Value: " << p->integer << std::endl;
}
else if (auto p = dynamic_cast<ErrorD const*>(&e)) {
std::cout << " Value: " << p->real << std::endl;
}
???
My only option seems to resort to 2. I would love to hear if there is any other suggestion.
With the help of std::exception_ptr, you might do something like:
void print_exception(const std::exception_ptr& eptr, int level = 0)
{
try
{
std::rethrow_exception(eptr);
}
catch (const ErrorI& e)
{
std::cerr << std::string(level, ' ') << "exception: " << e.what() << ": " << e.integer << std::endl;
}
catch (const ErrorD& e)
{
std::cerr << std::string(level, ' ') << "exception: " << e.what() << ": " << e.real << std::endl;
}
catch (const std::exception& e)
{
std::cerr << std::string(level, ' ') << "exception: " << e.what() << std::endl;
}
}
// prints the explanatory string of an exception. If the exception is nested,
// recurses to print the explanatory of the exception it holds
void print_exception_rec(const std::exception_ptr& eptr, int level = 0)
{
print_exception(eptr, level);
try {
try {
std::rethrow_exception(eptr);
}
catch (const std::exception& e)
{
std::rethrow_if_nested(e);
}
} catch(const std::exception&) {
print_exception_rec(std::current_exception(), level+1);
} catch(...) {}
}
Demo

c++ No exception thrown while expecting out_of_range

Consider the following source:
void ex8()
{
vector<int> v;
try
{
v.push_back(3);
int i = v[1];
}
catch (exception& e)
{
cout << "pas bon !";
}
}
When executing, no exception is thrown in Release. In Debug, I get a Debug Assertion Failed dialog.
I'am using Visual Studio on Win 10.
Is the vector implementation not supposed to throw an out_of_range exception?
Thank you.
Just an example with [] and at()
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v;
v.push_back(123);
v.resize(0);
try {
std::cout << "at() ";
std::cout << v.at(0) << std::endl;
}
catch (std::exception e) {
std::cout << e.what() << std::endl;
}
std::cout << "[] " << v[0] << std::endl; // all can append
return 0;
}
For me the execution is
at() std::exception
[] 123

What should I return in an error case in a function expected to return a Template<T> value?

I'm quite noob yet in OOP and is my first time handling exceptions and Templates, may be I planned the function in a wrong way...
But I would like to know what should I return in this case if the execution goes wrong and the exception is thrown.... what kind of data error return in a function returning a Template?
Sorry if I am not clear enough, english is not my mothertongue...
template<typename T>
const T& List<T>::Next()
{
try
{
if (_actual->getNext() == NULL)
throw out_of_range("No next elements, list out of bounds");
else
{
_actual = _actual->getNext();
_Position++;
return _actual->getData();
}
}
catch (out_of_range &e)
{
cerr << "Error, " << e.what() << endl << "Position: " << _Position << " Elements: " << _Elements << endl;
}
// <--- what should I return here?? return NULL;? return 0;? return <T> thrash;??
}
If there's nothing to return then there's nothing to return.
Let the exception propagate, either by not catching it here, or by re-throwing it after your cerr statement with the throw statement:
catch (out_of_range &e)
{
cerr << "Error, " << e.what() << endl
<< "Position: " << _Position
<< " Elements: " << _Elements << endl;
throw;
}
Your next question will be how to handle the exception in the calling scope. :)
But at least you won't have to worry about return values any more.

Cascade Poco Exception

I try to cascade exception in Poco.
void debug() {
try {
...
xmlFile.parseDocument(*_sim);
...
}
} catch (Poco::Exception& error) {
std::cout << "I'm here" << endl;
std::cout << "Error : " << error.displayText() << std::endl;
}
}
void XMLParser::parseDocument(Manager &manager) {
...
try {
Poco::XML::NodeList* policyList = root->childNodes();
for (uint node=0; node < policyList->length(); node++)
if (policyList->item(node)->hasChildNodes())
manager.insertRule(parseRule(node, policyList->item(node)));
} catch(Poco::Exception& error) {
std::cout << "Error : " << error.displayText() << std::endl;
error.rethrow();
}
}
Rule* XMLParser::parseRule(int flowID, Poco::XML::Node* rule) throw() {
....
if (tLink._srcPort < 0)
throw new Poco::Exception("Source Port isn't valid");
....
}
The deepest exception are thrown, but it does not continue to outer functions.
The program is terminated. Why?
You throw a Poco::Exception pointer so you can not catch it by reference.
Remove 'new'. This should work:
....
if (tLink._srcPort < 0)
throw Poco::Exception("Source Port isn't valid");
....