Consider the following example (taken from https://theboostcpplibraries.com/boost.exception)
#include <boost/exception/all.hpp>
#include <exception>
#include <new>
#include <string>
#include <algorithm>
#include <limits>
#include <iostream>
typedef boost::error_info<struct tag_errmsg, std::string> errmsg_info;
struct allocation_failed : public std::exception
{
const char *what() const noexcept { return "allocation failed"; }
};
char *allocate_memory(std::size_t size)
{
char *c = new (std::nothrow) char[size];
if (!c)
BOOST_THROW_EXCEPTION(allocation_failed{});
return c;
}
char *write_lots_of_zeros()
{
try
{
char *c = allocate_memory(std::numeric_limits<std::size_t>::max());
std::fill_n(c, std::numeric_limits<std::size_t>::max(), 0);
return c;
}
catch (boost::exception &e)
{
e << errmsg_info{"writing lots of zeros failed"};
throw;
}
}
int main()
{
try
{
char *c = write_lots_of_zeros();
delete[] c;
}
catch (boost::exception &e)
{
std::cerr << *boost::get_error_info<errmsg_info>(e);
}
}
The function allocate_memory() throws exception using the following statement
BOOST_THROW_EXCEPTION(allocation_failed{});
In the catch block how can I convert boost::exception &e back to allocation_failed?
Also, if my code has multiple throw statements like BOOST_THROW_EXCEPTION(A{}), BOOST_THROW_EXCEPTION(B{}), BOOST_THROW_EXCEPTION(C{}), etc. Where A, B, C are classes. Without using boost I can have separate catch blocks for each type of exception, in the following manner.
...
catch(A e){
...
}
catch(B e){
...
}
catch(C e){
...
}
How can I do the same when using boost, so that BOOST_THROW_EXCEPTION(A{}), BOOST_THROW_EXCEPTION(B{}), BOOST_THROW_EXCEPTION(C{}), etc. go to different catch blocks?
I am new to boost library, and some of its concepts elude me.
BOOST_THROW_EXCEPTION always throws a type which inherits the type of its argument, in addition to inheriting boost::exception. This means two things:
You can dynamic_cast from boost::exception to the type that was passed.
-
catch (boost::exception &e)
{
std::cerr << *boost::get_error_info<errmsg_info>(e);
if ( allocation_failed* af = dynamic_cast<allocation_failed*>(&e) )
{
std::cerr << af->what() << std::endl; // redundant
}
}
You can directly catch the type that was passed. However, you should always catch by reference to avoid slicing. (This advice is independent of whether you're using boost or whatever.)
-
catch (A& a) {
// ...
} catch (B& b) {
// ...
} catch (C& c) {
// ...
}
Of course, doing it this way, if you want any of boost's error formatting or extra data, you would need to then dynamic_cast the exception object to boost::exception*.
Related
#include <iostream>
#include <sstream>
using std::string;
using std::cout;
using std::endl;
using std::ostringstream;
class illegalParameterValue {
private:
string message;
public:
illegalParameterValue() : message("Illegal parameter value") {}
explicit illegalParameterValue(const char* theMessage) {message = theMessage;}
void outputMessage() {cout << message << endl;}
};
int main() {
ostringstream s;
s << "index = " << 1 << " size = " << 2;
throw illegalParameterValue(s.str().c_str());
return 0;
}
I just use some code like this, but the throw will remind some warnings which called
Clang-Tidy: Throwing an exception whose type 'illegalParameterValue' is not derived from 'std::exception'
How can I solve this problem?
consider the following code:
try {
// do something that might throw an exception
}
catch (const std::exception &ex) {
// handle the exception
}
If you derive your illegalParameterValue class from std::exception, then the catch clause above will catch it (along with other kinds of exceptions derived from std::exception). As currently written, it will not. Your users will have to add another catch clause:
try {
// do something that might throw an exception
}
catch (const std::exception &ex) {
// handle std exceptions
}
catch (const illegalParameterValue &ip) {
// handle illegal parameter exeception
}
Maybe that's what you want, maybe not.
But there's a lot of code out there like the first case.
How to build a custom string inside what() function of exception class and return it? The following code does not work but presents what I want to achieve:
class divide_by_zero : public exception {
public:
divide_by_zero(int a) : a(a) {}
const char * what() noexcept {
stringstream ss;
ss << "Division " << a << " by zero!";
return ss.str().c_str();
}
private:
int a;
};
How to build a custom string inside what() function of exception class and return it?
Don't do that. It won't work.
Instead, build the custom string inside the constructor, store the string in a member, and return a pointer to the data owned by the member in what.
Technically, you can delay building the string until the first call to what. The primarily important thing is to store the string in a member rather than a local variable, and to not invalidate the returned pointer. Such delay is unnecessary complexity however, it is simpler to build the string in the constructor.
Your local stringstream is being destroyed too early as it's only local.
Cache the message result with the exception object.
#include <iostream>
#include <stdexcept>
#include <sstream>
#include <string>
using std::cout;
using std::exception;
using std::stringstream;
using std::string;
class divide_by_zero : public exception {
public:
divide_by_zero(int aa) : a{aa} {}
const char * what() const noexcept override {
if (msg.empty()) {
stringstream ss;
ss << "Division " << a << " by zero!";
msg = ss.str();
}
return msg.c_str();
}
private:
int a;
mutable string msg;
};
int main() {
try {
throw divide_by_zero(75);
} catch(exception const& ex) {
cout << "Caught exception " << ex.what() << "\n";
}
}
UPDATE, or use eerorika's recommendation:
#include <iostream>
#include <stdexcept>
#include <sstream>
#include <string>
using std::cout;
using std::exception;
using std::stringstream;
using std::string;
class divide_by_zero : public exception {
public:
divide_by_zero(int a) : msg{make_msg(a)} {}
char const* what() const noexcept override {
return msg.c_str();
}
private:
string msg;
static string make_msg(int a) {
stringstream ss;
ss << "Division " << a << " by zero!";
return ss.str();
}
};
int main() {
try {
throw divide_by_zero(75);
} catch(exception const& ex) {
cout << "Caught exception " << ex.what() << "\n";
}
}
You can format and store that string in the constructor and return it later on:
#include <cstdio>
#include <exception>
class divide_by_zero : public std::exception {
public:
divide_by_zero(int const a) {
std::sprintf(buff, formatStr, a);
}
const char * what() const noexcept override {
return buff;
}
private:
static constexpr auto& formatStr = "Division %d by zero!";
char buff[sizeof(formatStr) + 20];
};
This does no dynamic allocation, which is better in the case of exception handling.
I'm trying to create a class with a method to handle all exceptions. It accepts a pointer to a function, executes that function and then will handle if the function throws an exception. I then created a function get an invalid substring to prove the exception is caught, however, my class isn't getting the exception and Visual Studio is breaking on the substring line saying "Exception Unhandled"
cpp file:
#include "TestHarness.h"
using namespace TestHarness;
int testFunc();
int main()
{
Tester myTest;
std::cout << myTest.execute(testFunc);
return 0;
}
int testFunc()
{
std::cout << "My Test Func" << std::endl << std::endl;
std::string("abc").substr(10);
return 6;
}
h file:
#define TESTHARNESS_H
#include <vector>
#include <iostream>
#include <sstream>
#include <string>
namespace TestHarness
{
class Tester
{
public:
int execute(int(*func)());
private:
bool result;
};
int Tester::execute(int(*func)())
{
try {
(*func)();
result = true;
return 1;
}
catch (const std::runtime_error& e)
{
std::cout << e.what();
result = false;
return 0;
}
}
}
#endif
It's simple, really: substr throws std::out_of_range, which does not derive from std::runtime_error but from std::logic_error, itself derived from std::exception. Just catch std::exception const & or std::logic_error const &. Here is a list of inheritance for all standard exception types.
I have following code,
my_class.cpp
#include "my_class.h"
my_class::my_class(int m)
{
try
{
my_method();
throw My_Exception();
}
catch(exception &e)
{
delete this;
throw;
}
}
my_class::~my_class()
{
for(auto &el : my_member)
if(el!=NULL)
delete el;
}
void my_class::my_method()
{
for(int i ; i<5 ; i++)
my_member.push_back(new dfa(i)); //dfa is another class
}
my_class.h
#include "dfa.h"
#include "exception.h"
using namespace std;
class my_class
{
public :
my_class();
~my_class();
void my_method();
private :
vector<dfa *> my_member;
};
exception.h
#include <exception>
class My_Exception : public exception
{
public:
const char * what () const throw ()
{
return "Generic Exception";
}
};
main.cpp
#include <iostream>
#include "my_class.h"
int main()
{
try
{
my_class *ptr = new my_class(3);
}
catch(exception &e)
{
cout<<e.what()<<endl;
}
}
the class dfa is missing, but is a normal class. The problem is in the catch, when i do delete this the denstructor is invoked and dynamics objects of class dfa deallocated but the exception isn't relaunched. The execution flow doesn't return to main (in the catch block of the main) because there is a segmentation fault. What could be the problem?
(I can't use shared or auto ptr to handle memory because I'm using a big library)
(I'm using C++11)
delete does a lot more work than just calling the destructor.
You cannot call delete on an incomplete object, which is the case since the constructor never completed successfully.
The implication is that when handling exceptions in a constructor, you need to do the cleanup yourself, but you cannot simply call delete, as this will conflict with the way new deals with exceptions.
Here's a way to fix this:
my_class::my_class(int m)
{
try
{
my_method();
throw My_Exception();
}
catch(exception &e)
{
cleanup();
throw;
}
}
void my_class::cleanup() {
for(auto &el : my_member)
if(el!=NULL)
delete el;
}
my_class::~my_class()
{
cleanup();
}
Is it possible to capture and print name of the function which initialized a class object? What I want is something like this:
class MyException: public std::exception
{
public:
MyException(const std::string message, const std::string caller = __func__)
: _caller(caller),
_msg(message)
{
...
}
std::string what(void); // prints messaged along with the caller
private:
...
}
In the above class MyException I want the caller to capture the function name where an object was instantiated so that user is warned of which function threw. I can always do
...
throw MyException(message, __func__);
...
while removing the default __func__. But then I am doing this trivial thing every time I instantiate an MyException object.
Is there a better way to instruct user exactly which function throws?
Thanks in advance,
Nikhil
If I wanted to provide automatic context for my exceptions I'd do it like this:
#include <iostream>
#include <stdexcept>
#include <string>
struct context_info {
explicit context_info(std::string function)
: _function { std::move(function) }
{}
// perhaps the context info will increase later to include class and instance?
friend std::string to_string(const context_info& ci)
{
return ci._function;
}
private:
std::string _function;
};
struct my_exception : std::runtime_error
{
my_exception(const std::string& message)
: std::runtime_error(message)
{}
my_exception(context_info context, const std::string& message)
: my_exception(message + " called from " + to_string(context))
{}
// everything else already taken care of for you
};
#if defined(NDEBUG)
#define THROW_WITH_CONTEXT(TYPE, ...) throw TYPE(__VA_ARGS__)
#else
#define THROW_WITH_CONTEXT(TYPE, ...) throw TYPE(context_info(__func__), __VA_ARGS__)
#endif
using namespace std;
void do_foo()
try {
THROW_WITH_CONTEXT(my_exception, "foo failure");
}
catch(const exception& e) {
cout << e.what() << endl;
}
int main() {
// your code goes here
try {
do_foo();
THROW_WITH_CONTEXT(my_exception, "error");
}
catch(const exception& e) {
cout << e.what() << endl;
}
return 0;
}
expected output:
foo failure called from do_foo
error called from main
However, neat as this is it's probably not what you should really be doing as it won't provide you with enough context in a large complex program.
have a look at the documentation for std::throw_with_nested etc. You can catch an exception at each stage of the call stack and re-throw it with additional context information. This is much more useful.
http://en.cppreference.com/w/cpp/error/throw_with_nested