Exceptions & C-style strings - c++

I've problem with exceptions:
#include <iostream>
#include <cstring>
#include <exception>
class except :public std::exception
{
char* err;
public:
except(const char* s) noexcept
{
err = new char[strlen(s) + 1];
strcpy(err, s);
err[strlen(s)] = 0; //is it necessary??
}
virtual const char* what() noexcept
{return err;}
virtual ~except() noexcept
{delete err;}
};
double div(const double& a, const double& b) noexcept
{
if (b == 0.0)
throw except("DIVIDED BY 0");
return a / b;
}
int main()
{
try
{
std::cout << div(5.0, 0.0);
}
catch (std::exception &ex)
{
std::cout << ex.what();
}
return 0;
}
I want to print "DIVIDED BY 0" but I get:
terminate called after throwing an instance of 'except'
what(): std::exception
Aborted
Process returned 134 (0x86)
Shall I put noexcept in every function/member function that doesn't throw any exceptions?
Is err[strlen(s)] = 0 necessary? (in except::except(const char* s))

I want to print "DIVIDED BY 0" but I get: terminate called after throwing an instance of 'except'
double div(const double& a, const double& b) noexcept
You are claiming that you won’t throw an exception, but you are lying. The result is the call to std::terminate when you actually throw.

The problem is a actually twofold. Firstly, as #manni66 suggests, div should not be declared noexcept and this does cause a run-time error, but removing it does not solve the issue.
The second problem is that what has been declared:
virtual const char* what() noexcept;
whereas it's declared in std::exception as:
virtual const char* what() const noexcept;
and this difference in signature means that when it's caught by the handler for std::exception, it calls std::exception::what() and not except::what()
A couple of points worth mentioning:
Ensure that your function overloads exactly match those in the base class.
If you are expecting a certain type of exception to be thrown then try to catch that first with a specific handler and use an appropriate name for the exception for clarity.
As others have mentioned, please try to use the std::string class if you can. It will make things easier and safer. Although in this case, as point two eludes to, a string member is not really necessary as the class is specific enough not to need further qualification.
Don't create an exception class unless it's adding some specific value (though the value, may simply be that you want to specifically catch a certain type of exception and handle in a certain way.) If you wanted a more general exception then std::runtime_error or in this case std::overflow_error would be decent choices and both take a std::string as an argument to the constructor, so no need to create your own exception class.
For example:
#include <exception>
using namespace std;
class divide_by_zero : public std::exception
{
public:
virtual const char* what() const noexcept { return "DIVIDED BY 0"; }
};
double div(const double& a, const double& b)
{
if (b == 0.0)
throw divide_by_zero();
return a / b;
}
int main()
{
try
{
std::cout << div(5.0, 0.0);
}
catch (divide_by_zero &ex)
{
std::cout << ex.what();
}
catch (std::exception &ex)
{
std::cout << ex.what();
}
return 0;
}
Output:
DIVIDED BY 0

Related

C++ exception class extension syntax

I am taking a course online and came across some syntax I am not really sure I understand.
#include <iostream>
#include <exception>
using namespace std;
class derivedexception: public exception {
virtual const char* what() const throw() {
return "My derived exception";
}
} myderivedexception;
int main() {
try {
throw myderivedexception;
}
catch (exception& e) {
cout << e.what() << '\n';
}
}
My Problem is with:
virtual const char* what() const throw()
What does this line mean?
also, what is with the
} myderivedexception;
in the end of the class declaration?
This line:
virtual const char* what() const throw()
says that what is a virtual method that returns a pointer to a constant char (which means it can be used to return a string literal, or the contents of a std::string obtained by calling the string::c_str() function), is itself constant so it doesn't modify any class members, and it does not throw any exceptions.
This line:
} myderivedexception;
creates an instance of the derivedexception class named myderivedexception. You probably do not want to do this, but instead throw an unnamed exception:
throw derivedexception();

Catching strings for output

I have a try catch statement in my main function
try
{
app.init();
}
catch(std::string errorMessage)
{
std::cout << errorMessage;
return 1;
}
but when I throw "SOME_ERROR"; The console output is simply
terminate called after throwing an instance of 'char const*'
Aborted (core dumped)
How can I make errorMessage output to the console?
Please do not throw anything which is not derived from std::exception.
An exemption might be an exception intended to terminate the program (providing an internal state, though)
You either intend to throw std::string OR catch const char*:
throw std::string("error")
catch(const char* message)
However as pointed out, it's better just to derive from std::exception:
#include <iostream>
// must include these
#include <exception>
#include <stdexcept>
struct CustomException : std::exception {
const char* what() const noexcept {return "Something happened!\n";}
};
int main () {
try {
// throw CustomException();
// or use one already provided
throw std::runtime_error("You can't do that, buddy.");
} catch (std::exception& ex) {
std::cout << ex.what();
}
return 0;
}
You need to derive something from std::exception. <--if you want memory safety
It has a method: virtual const char* ::std::exception::what() const noexcept;
Build your char* you want to see in the constructor, store it, return it for what() then free it in the destructor for memory safe exceptions.

How to supplement boost::exception with a proper what() function

I like boost::exception quite a bit, but I'm quite bothered it does not provide a proper what() function out of the box. Now don't get confused, it does have a nice boost::diagnostic_information that contains all the information I would like to see in my hypothetic what() function but since boost::exception does not inherit from std::exception the what() function I get if I multiple inherit (as suggested from the tutorial, see line below) is the default useless what() from the std::exception base that explains nothing about the exception.
struct my_exception: virtual std::exception, virtual boost::exception { };
Now obviously I tried to override what() and make it return boost::diagnostic_information but somehow it just does not work, so I'm a bit puzzled. That might be because it would loop but I'm not quite sure.
PS: The reason I want to implement what() right is that it is shown by default by a lot of tools if your program dies from them (e.g. the gnu compiler will show a nice fatal error, and display what(), boost unit tests tools etc.).
Here's a link to the test code below
#include <boost/exception/all.hpp>
struct my_exception: virtual std::exception, virtual boost::exception {};
struct my_exception2: virtual std::exception, virtual boost::exception {
virtual const char* what() const throw() {
return "WHAT";
}
};
struct my_exception3: virtual std::exception, virtual boost::exception {
virtual const char* what() const throw() {
return boost::diagnostic_information(this).c_str();
}
};
int main() {
try {
BOOST_THROW_EXCEPTION(my_exception());
} catch (const std::exception& e){
std::cout << e.what() << std::endl;
//This is useless ___ std::exception
}
try {
BOOST_THROW_EXCEPTION(my_exception());
} catch (const boost::exception& e){
std::cout << boost::diagnostic_information(e) << std::endl;
//This is what I'd like to see ___ main.cpp(39): Throw in function int main() ___ Dynamic exception type: boost::exception_detail::clone_impl ___ std::exception::what: std::exception
}
try {
BOOST_THROW_EXCEPTION(my_exception2());
} catch (const std::exception& e){
std::cout << e.what() << std::endl;
//Overriding what usually works ___ WHAT
}
try {
BOOST_THROW_EXCEPTION(my_exception3());
} catch (const std::exception& e){
std::cout << e.what() << std::endl;
//But somehow here it does not work ___ Unknown exception.
}
}
First, boost::diagnostic_information takes an exception by (const) reference, and this is a pointer:
return boost::diagnostic_information(*this).c_str();
^-- here
Second, once you've fixed that, as you've correctly anticipated this results in infinite recursion as boost::diagnostic_information calls std::exception::what(). It is possible to work around this with a guard member or something similar:
struct my_exception3: std::exception, boost::exception {
mutable bool in_what = false;
virtual const char* what() const throw() {
struct g { bool &b; ~g() { b = false; } } guard{in_what};
return in_what ? "WHAT" : (in_what = true, boost::diagnostic_information(*this).c_str());
}
};
Finally, you're using c_str from a destructed temporary string. I'll leave the solution to that problem as an exercise.
And the winner is...
namespace boost {
char const * diagnostic_information_what( boost::exception const & e ) throw();
}

How to throw an exception by its run-time type?

I want to call a function that may throw an exception. If it does throw an exception, I want to catch it and pass the exception object to a handler function. The default implementation of the handler function is simply to throw the exception. Here is whittled-down code to illustrate the issue:
struct base_exception : exception {
char const* what() const throw() { return "base_exception"; }
};
struct derived_exception : base_exception {
char const* what() const throw() { return "derived_exception"; }
};
void exception_handler( base_exception const &e ) {
throw e; // always throws a base_exception object even if e is a derived_exception
}
int main() {
try {
throw derived_exception();
}
catch ( base_exception const &e ) {
try {
cout << e.what() << endl; // prints "derived_exception" as expected
exception_handler( e );
}
catch ( base_exception const &e ) {
cout << e.what() << endl; // prints "base_exception" due to object slicing
}
}
}
However, the throw e in exception_handler() throws a copy of the static type of the exception, i.e., base_exception. How can I make exception_handler() throw the actual exception having the correct run-time type of derived_exception? Or how can I redesign things to get what I want?
You can put a throw_me virtual function in the base exception class, and have every derived class override it. The derived classes can throw the proper most derived type, without slicing. Even though the function has the same definition in each class, they're not the same - the type of *this is different in each case.
struct base_exception : exception
{
char const* what() const throw() { return "base_exception"; }
virtual void throw_me() const { throw *this; }
};
struct derived_exception : base_exception
{
char const* what() const throw() { return "derived_exception"; }
virtual void throw_me() const { throw *this; }
};
void exception_handler( base_exception const &e ) {
e.throw_me();
}
You can use throw; to re-throw the exception that was caught. You could also use a template.
template<typename T> void rethrow(const T& t) { throw t; }
Throw by value, catch by reference. It'll save you a lot of headaches.
What you are looking for is called "propagating" the exception. To do so, you have to use the throw keyword without parameters inside the catch block. It will not copy the exception and the exception will be caught by the next catch block on its way or will make your program abort if it's not caught again.

Catch with multiple parameters

First I found in cplusplus.com the following quote:
The catch format is similar to a regular function that always has at least one parameter.
But I tried this:
try
{
int kk3,k4;
kk3=3;
k4=2;
throw (kk3,"hello");
}
catch (int param)
{
cout << "int exception"<<param<<endl;
}
catch (int param,string s)
{
cout<<param<<s;
}
catch (char param)
{
cout << "char exception";
}
catch (...)
{
cout << "default exception";
}
The compiler doesn't complain about the throw with braces and multiple arguments. But it actually complains about the catch with multiple parameters in spite of what the reference said. I'm confused. Does try and catch allow this multiplicity or not? And what if I wanted to throw an exception that includes more than one variable with or without the same type.
(kk3, "hello") is a comma expression. The comma expression evaluates all of its arguments from left to write and the result is the rightmost argument. So in the expression
int i = (1,3,4);
i becomes 4.
If you really want to throw both of them (for some reason) you could throw like this
throw std::make_pair(kk3, std::string("hello"));
and catch like this:
catch(std::pair<int, std::string>& exc)
{
}
And a catch clause has exactly one argument or
...
HTH
In addition to the other answers, I would recommend you to create your own exception class that can contain more than one piece of information. It should preferably derive from std::exception. If you make this a strategy, you can always catch your exceptions with a single catch(std::exception&) (useful if you only want to free some resource, and then rethrow the exception - you don't have to have a gazilion catch handlers for each and every exception type you throw).
Example:
class MyException : public std::exception {
int x;
const char* y;
public:
MyException(const char* msg, int x_, const char* y_)
: std::exception(msg)
, x(x_)
, y(y_) {
}
int GetX() const { return x; }
const char* GetY() const { return y; }
};
...
try {
throw MyException("Shit just hit the fan...", 1234, "Informational string");
} catch(MyException& ex) {
LogAndShowMessage(ex.what());
DoSomething(ex.GetX(), ex.GetY());
}