Relaunch an exception in a constructor later instruction delete this - c++

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();
}

Related

Exception not be caught by class and visual studio 2019 stopping at "Exception Unhandled"

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.

Exception in aggregate initialization

In C++14 (gcc 6.3) I have the following code:
#include <memory>
#include <vector>
#include <stdexcept>
struct A
{
int a1;
int a2;
};
struct B
{
int b1;
std::shared_ptr< std::vector<A> > Alist;
};
struct C
{
std::shared_ptr<B> b;
std::shared_ptr< std::vector<A> > Alist;
};
std::shared_ptr< std::vector<A> > makeListA()
{
std::vector<A> toto = {{0,1}, {2,3}};
return std::make_shared< std::vector<A> >(toto);
}
std::shared_ptr< std::vector<A> > makeListAWithException()
{
throw std::out_of_range("My exception");
}
std::shared_ptr<B> makeB()
{
return std::make_shared<B>(B{0, makeListA()});
}
main()
{
std::make_unique<C>(C{makeB(),makeListAWithException()});
}
When running valgrind i have a memory leak : it looks like the objects created by "makeB()" function were not freed. I had this problem only when using aggregate initialization with curly braces.
When I define an explicit constructor on each class (A, B and C), I don't have this issue.
What am I doing wrong ?
Best regards
This is gcc bug 66139. Here is a short reproduction, courtesy of Andrzej (with a more thorough description available in the blog post):
#include <cstdio>
#include <stdexcept>
struct Resource
{
explicit Resource(int) { std::puts("create"); }
Resource(Resource const&) { std::puts("create"); }
~Resource() { std::puts("destroy"); }
};
Resource make_1() { return Resource(1); }
Resource make_2() { throw std::runtime_error("failed"); }
struct User
{
Resource r1;
Resource r2;
};
void process (User) {}
int main()
{
try {
process({make_1(), make_2()});
}
catch (...) {}
}
This prints:
create
It should print (as clang, correctly, does):
create
destroy
You don't have associated try/catch so your program terminate.
stack unwinding is not required in that case.
Following should solve your possible leak.
int main()
{
try
{
std::make_unique<C>(C{makeB(), makeListAWithException()});
}
catch (...)
{
}
}
if you change to like below, i think the problem is fixed
std::make_unique<C>(C{makeB(),makeListAWithException()});
to
auto b = makeB();
std::make_unique<C>(C{b,makeListAWithException()});

How to cast boost::exception?

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*.

C++ Exceptions and handling

I am new to writing exceptions in c++ and I am struggling with an error. I won't get very much into detail 'cause I don't think this is relevant for the problem that I have.
#ifndef _STUDENT_H_
#define _STUDENT_H_
#include <string>
#include <map>
#include <vector>
#include <stdexcept>
#include <iostream>
class NoMarkException: public exception
{
public: NoMarkException():exception(){
cout<< "No marks were found." << endl;
}/*
NoMarkException(const string &name){
cout << "No marks for " << name << " were found."<< endl;
}*/
};
#endif
This is my NoMarkException class
float Student::getMaxMark() const throw(NoMarkException) {
if (marks.empty()) {
throw NoMarkException::NoMarkException();
}
float final = 0;
for (it = marks.begin(); it != marks.end(); it++) {
if ((*it).second > final) {
final = (*it).second;
}
}
return final;
}
And this is my Student.cpp
When I am building the project I get error: cannot call constructor 'NoMarkException::NoMarkException' directly
Any ideas why it is causing the problem?
if (marks.empty()) {
throw NoMarkException();
}
The error you get does not actually have anything to do with the fact you're using an exception class. The problem is that you're trying to instantiate an object of class NoMarkException by explicitly calling the (default) constructor, NoMarkException::NoMarkException(). In C++ you don't call constructors explicitly; rather, when you define a new variable, an appropriate constructor gets called. For example
void foo() {
std::vector<int> v(5);
NoMarkException my_exception();
NoMarkException my_other_exception();
}
or, using equivalent but more appropriate due to recent language changes:
void foo() {
std::vector<int> v { 5 };
NoMarkException my_exception { };
NoMarkException my_other_exception { };
}
In this case (both syntax alternatives), the constructors:
std::vector<int>::vector(std::vector<int>::size_type count)
NoMarkException::NoMarkException()
NoMarkException::NoMarkException()
are called (*).
In your case, you simply need to replace the explicit call you make to NoMarkException::NoMarkException() in the throw with an instantiation of NoMarkException object, i.e. your statement will be:
throw NoMarkException();
(*) - actually, the vector constructor that's called has a few more parameters which take their default values. See here.

Printing name of the initializing function for a class

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