C++ Custom Exception classes - c++

i am making a program and decided to make my own exceptions so i wrote the following header-only file:
#ifndef ARGUMENT_EXCEPTIONS
#define ARGUMENT_EXCEPTIONS
#include <exception>
namespace AAerr {
class ArgumentException : public std::exception {
private:
const char* msg;
static constexpr char* funcName = (char*)"ArgumentException";
public:
ArgumentException(const char* msg_) {
msg = msg_;
}
const char* getMessage() {
return msg;
}
virtual const char* what() const throw() {
return funcName;
}
};
class WrongReturnType : public ArgumentException {
private:
const char* msg = "Wrong Type";
char requestedType;
char ofType;
static constexpr char* funcName = (char*)"WrongReturnType";
public:
WrongReturnType(const char requested, const char is) : ArgumentException(msg) {
requestedType = requested;
ofType = is;
}
char get_requested_type() {
return requestedType;
}
char get_of_type() {
return ofType;
}
virtual const char* what() {
return funcName;
}
};
}
#endif // ARGUMENT_EXCEPTIONS
and when i tried to throw and catch one of them in my program it never caught anything:
#include "exception_header_file.hpp" // the name of the header file
#include <iostream>
int main() {
try {
throw AAerr::ArgumentException("TEST");
} catch (AAerr::ArgumentException& exc) {
std::cout << "CAUGHT EXCEPTION" << std::endl; // never executed
}
}
and then i made a second file (just to figure out where the problem is):
#include <iostream>
#include <exception>
namespace AAerr {
class Exc : public std::exception {
private:
const char* msg;
static constexpr char* funcName = (char*)"TEST FUNC";
public:
Exc(const char* msg_) {
msg = msg_;
}
const char* getMessage() {
return msg;
}
virtual const char* what() {
return funcName;
}
};
class Exc2 : public Exc {
private:
int line;
static constexpr char* funcName = (char*)"FUNCTION";
public:
Exc2(const char* msg_, int line_) : Exc(msg_) {line = line_;}
virtual const char* what() {
return funcName;
}
};
};
int main() {
try {
throw Exc2("TEST", 5);
} catch (AAerr::Exc& exc) {
std::cout << "CAUGHT EXCEPTION" << std::endl; // works fine
}
}
can someone help me find where the problem is?? i can't find any difference between these 2.
compiler: g++(gcc)
platform: ubuntu(linux)
EDIT:
i managed to fix the problem.
it was on the on the linker(ld).
i changed my Makefile to build the whole project instead of making and then linking everything.
what i mean is, i did:
build:
g++ program_part1.cpp program_part2.cpp program_part3.cpp -o example.elf
instead of:
build: part1.o part2.o part3.o
g++ part1.o part2.o part3.o -o output.elf
part1.o: program_part1.cpp program_part1.hpp
g++ -c program_part1.cpp -o part1.o
...
...

I suspect that problem is in "main program", see OP comment in other answer:
yeah i tried and it's the same thing. it doesn't work on my main program, but works fine on the testing program i have – user898238409
If "main program" is using dynamic libraries and exception are defined as "header only", this can lead to situation that RTTI (Run Time Type Information) is generated for this class multiple times. One for each include for dynamic library and main executable where this header file is included.
For example this can go like this:
dynamic library creates instance of class AAerr::ArgumentException using RTTI generated for that library when exception and throws this as exception.
main executable is trying catch that exception using RTTI which was build for that executable.
Since those two RTTI do not match to each other catch statement can't notice that expected exception is thrown.
Proper fix for that is to drop "header only" exceptions so all virtual methods should be defined in cpp file. This will lead to well defined association with specific library. As a result only one RTTI will be present for ArgumentException and WrongReturnType.

Have you tried catching std::exception instead of the exception class?
Like this:
try{
throw AAerr::Argument exception("Test");
} catch (std::exception exc) {
std::cout << "HEY" << std::endl;
}

Related

Why " throw" will display a warning?

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

Returning custom string from exception::what()

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.

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.

When catching a boost::bad_lexical_cast, can I access the string/token which was to be cast?

I'm running code which might throw a boost:bad_lexical_cast when casting a sequence of tokens - but I can't go into the code and "put the tokens aside" so I can figure out what cast actually failed.
Does boost:bad_lexical_cast let you access that string it had attempted to cast somehow? I could not seem to find anything in its definition except for some fields regarding type names, but maybe there's something I'm missing.
if you have control of the code that calls lexical_cast, then you can use function try blocks to catch, wrap and re-throw the exception with extra information:
#include <boost/lexical_cast.hpp>
#include <string>
#include <stdexcept>
#include <exception>
struct conversion_error : std::runtime_error
{
conversion_error(const std::string& name, const std::string& value)
: std::runtime_error::runtime_error("converting " + name + " : " + value)
, name(name)
, value(value)
{}
const std::string name, value;
};
struct test
{
void bar()
{
try {
foo();
} catch(const conversion_error& e) {
std::cerr << e.what() << std::endl;
}
}
void foo()
try
{
i = boost::lexical_cast<int>(s);
}
catch(...)
{
std::throw_with_nested(conversion_error("s", s));
}
std::string s;
int i;
};
int main()
{
test a { "y", 0 };
a.bar();
}

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