Hi everyone I would like to add exception handling for a couple conditions. Parentheses mismatch when unstacking and and if the expression entered by the user doesn't start and end with #. Mostly just looking for pointers and tips for expression handling in a class and main not a solution.
Here's what I was thinking but its obviously not correct.
This is done in my infixtopost class and I have class invalidExp(){} declared in my header file.
The other exception I tried to handle in main checking the line of input from the user with
if(line[0] != '#' || line[line.length()] != '#') throw "Invalid Expression"
but it would skip over this line and when I put it in a try catch block the rest of the code couldn't exectue.
while (!op->isEmpty() && op->top() != '(') throw invalidExp();
{
post.push_back(op->pop());
if (!op->isEmpty())
{
op->pop();
} //to remove ( from stack
}
main:
try{
IntoPost *infix = new IntoPost(token.length());
post = infix->inToPost(token);
cout << post << "=";
Evalexp *result = new Evalexp(post.length());
result->evalExp(post);
result->print();
}
catch (IntoPost::invalidExp){
cout << "Exception: Invalid Expression" << endl;
}
As I understand your question, you want to declare some custom exception types to handle errors in a clean way. Thats good and the following code will be an example of how this can be done. It's all just an example, to show what is possible.
0: Understanding throw
You can read more about throw here. But in general you can throw anything. throw 1; will throw an int for example. Your example throw "Invalid Expression" will throw a const char*. Usually you want to throw an object of a class that inherits from std::exception.
1: Declare a class for each type of exception you need to handle
It's good practice to let them extend from std::exception. In the constructor I usually create the exception message and pass it to the constructor of std::exception. So the following are just examples:
class ExceptionA : public std::exception {
public:
ExceptionA() : std::exception("Case A occurred!") { }
};
class ExceptionB : public std::exception {
public:
static string CreateMessage(int x, int y) {
// You can create a custom exception message here
}
ExceptionB(int x, int y) : std::exception(ExceptionB::CreateMessage(x, y)) {}
};
As you see in ExceptionB it's totally fine to attach additional data to your exception. This will help you to create a more specific exception message.
2: Sorround your code with a try-multicatch
You can read more about this here
It means, you can use multiple catch-blocks for each try-block.
void foo() {
try {
// Calcultion starts here
// Now you get unexpected input or something like this and signal it by throwing an exception.
if(errorCondition) { throw ExceptionA(); }
// Something else might happen here, so you throw the other type of exception
// in this example ExceptionB also takes two custom parameters.
if(otherErrorCondition) { throw ExceptionB(x, y); }
}
catch(ExceptionA &e) {
// Handle an occurence of Exception A
}
catch(ExceptionB &e) {
// Handle an occurence of Exception B
}
catch(std::exception &e) {
// Handle an occurrence of any other exceptions STL-components migth throw for example std::range_error
}
catch(...) {
// Handle the occurrence of any other thrown ... things. This will also catch things like throw 1, but usually you don't need this.
}
}
Here the order of the catch-blocks is important!
3: Enjoy clean exception handling!
I hope this answers your question!
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 months ago.
Improve this question
I have been reading a book where the object oriented implementation for exceptions is as follows:
Rectangle.hpp
class Rectangle
{
private:
// code
public:
class NegativeSize
{
// empty class declaration
// for exception
};
// code
};
Whenever a specific error occurs, the NegativeSize() is thrown from the constructor as follows:
Rectangle.cpp
void Rectangle::setX(int _x)
{
if (_x < 0)
{
// this instantiates an object
throw NegativeSize();
}
x = _x;
}
main.cpp
try
{
// code
}
catch (Rectangle::NegativeSize)
{
cout << "Negative value entered" << endl;
}
But I can do the same thing by declaring a public variable in Rectangle class and throw it instead:
Rectangle.hpp
class Rectangle
{
private:
// code
public:
string NegativeVal;
// code
};
Rectangle.cpp
void Rectangle::setX(int _x)
{
if (_x < 0)
{
throw NegativeSize;
}
x = _x;
}
main.cpp
try
{
// code
}
catch (string NegativeSize)
{
cout << "Negative value entered" << endl;
}
Can the second implementation be considered a good practice?
The actual exception object that the catch clause will catch is not the object that you name or refer to in the throw expression. Instead the exception object is an object of the same (decayed) type as the throw operand and initialized from the same.
So in your first example you throw an object of type Rectangle::NegativeSize which is initialized from NegativeSize() and in the second example you throw a std::string which is a copy of the NegativeSize member, whatever value it holds at that time.
In the second example catch (Rectangle::NegativeSize) will not work, because NegativeSize is not a type anymore. You will need to catch std::string instead, which of course is a problem, since it doesn't tell you at all what the kind of exception this is (plus some other deeper issues).
Throwing a std::string instead of a specific exception class is therefore not a good practice. You wouldn't be able to differentiate different exceptions and catch only those you can handle in a given catch clause.
Throwing a data member also seems pointless. What value will you set it to? Probably just the "Negative value entered" string? If so, that could be thrown directly as throw std::string("Negative value entered"); as well. As I said above, the exception object is going to be a copy anyway. At the catch clause you can't identify anymore that the throw expression used the NegativeSize member.
Also, in practice exception classes are usually derived from std::exception or a class derived from it and are not empty. They commonly store a string which can be given at the point of the throw expression, so that detailed information from the source of the exception can be provided to the user, e.g.:
class Rectangle
{
private:
// code
public:
struct NegativeSize : std::invalid_argument {};
// code
};
//...
void Rectangle::setX(int _x)
{
if (_x < 0)
{
throw NegativeSize("Negative value entered");
}
x = _x;
}
//...
try
{
// code
}
catch (const Rectangle::NegativeSize& e)
{
cout << e.what() << endl;
}
Also, as I do above, exceptions should usually be caught by-reference.
This is a (modified) problem from a test last week.
I was given an exception class with a predefined number in it:
class ErrorException {
/**
* Stub class.
*/
private :static long ErrorCode;
public: ErrorException( string str) {
cout <<str;
}
};
long ErrorException::ErrorCode = -444;
I think I was supposed to do was catch the exception and then return the number as an error code, but I could not figure out how to get the number in. I could make the catch return a string but not the number as string:
#include "stdafx.h"
#include <iostream>
#include "ErrorException.h"
#include "errno.h""
#include <string>;
class FillerFunction {
public :
virtual int getFillerFunction(int x) throw (ErrorException) = 0;
} // this notation means getFillerFunction is always throwing ErrorException?
double calculateNumber(int y){
//.....
try{
if (y !=0){
throw(ErrorException(?????))
}
};
double catchError(){
catch(ErrorException& x);
};
I eventually made it return the string "error" which is no better than using an if statement. I've looked up other catch-throw examples in c++ and dynamic exceptions, but I can't find an example with an exception grabbing a variable defined in the class.How do I access the ErrorCode, save changing the return type of ErrorException()?
Though this question has already been answered, I just want to add a few notes on proper exception handling in C++11:
First, throw(ErrorException) should not be used, as it is deprecated: http://en.cppreference.com/w/cpp/language/except_spec
Also, it is generally advisable to make use of the fact that C++ provides standard exception classes, personally I usually derive from std::runtime_error.
In order to really take advantage of the exception mechanism in C++11, I recommend using std::nested_exception and std::throw_with_nested as described on StackOverflow here and here. Creating a proper exception handler will allow you to get a backtrace on your exceptions inside your code without need for a debugger or cumbersome logging. Since you can do this with your derived exception class, you can add a lot of information to such a backtrace!
You may also take a look at my MWE on GitHub, where a backtrace would look something like this:
Library API: Exception caught in function 'api_function'
Backtrace:
~/Git/mwe-cpp-exception/src/detail/Library.cpp:17 : library_function failed
~/Git/mwe-cpp-exception/src/detail/Library.cpp:13 : could not open file "nonexistent.txt"
In your throw you're constructing an exception object. If you prefer to pass a number, you must provide the appropriate constructor.
Quick and dirty:
class ErrorException {
private :
static long ErrorCode;
public:
ErrorException( string str) {
cerr <<str<<endl;
}
ErrorException( long mynumeric code) {
cerr <<"error "<<mynumericcode<<endl;
}
};
The catching should look like:
double calculateNumber(int y){
try {
if (y !=0){
throw(ErrorException(227));
}
} catch(ErrorException& x) {
cout << "Error catched"<<endl;
}
}
Must be elaborated further
It's unusual to to print something in the exception constructor. You'd better populate the information needed in the catch, so that these information could later be accessed with the appropriate getter. The printing would then occur in the exception handler.
If you have a static error code, I suppose that somewhere you have a function that returns the last error code whatever happened. So maybe you'd update this code (but how do you intend to update it with the existing string alternative ?
Here how it could look like:
class ErrorException {
private :
static long LastErrorCode;
long ErrorCode;
string ErrorMessage;
public:
ErrorException(long ec, string str) : ErrorCode(ec), ErrorMessage(str)
{
LastErrorCode = ec;
}
static long getLastError() const { return LastErrorCode; } // would never be reset
long getError() const { return ErrorCode; }
string getMessage() const { return ErrorMessage; }
};
The catching should look like:
double calculateNumber(int y){
try {
if (y !=0){
throw(ErrorException(227,"y is not 0"));
}
} catch(ErrorException& x) {
cerr << "Error "<<x.getError()<<" : "<<x.getMesssage()<<endl;
}
cout << "Last error ever generated, if any: " << ErrorException::getLastErrror()<<endl;
}
Neverthesess, I'd advise you to have a look at std::exception before reinventing the wheel.
I've got a few questions about throwing exceptions in C++.
From what I know about them...
An exception can be thrown from within the main() function. Any block of code that can throw an exception in the main() function should be surrounded by try and catch statements as follows
void foo(//args) {
if (...) {
throw "Error reached";
} ...
int main() {
...
try {
//Code that can throw an excpetion
} catch(const char* msg) (
cerr << msg << endl;
}
...
}
In the example above, why is the argument to the catch a const char *. Doesn't C++ allow for strings? Also, is it possible to throw an exception that isn't a const char *, like an int? or a char?
Does throwing an exception in foo, terminate the foo function?
Are there cases where you could put the try and catch statements in the same function as the throw?
Sorry if these are basic questions.
Thanks SO
why is the argument to the catch a const char *
Because you threw string literal which decays to const char*. In short, you catch what you throw.
Doesn't C++ allow for strings?
It does, but to catch string, you need to throw string in first place.
is it possible to throw an exception that isn't a const char *,
You can throw literally anything. It is a good idea to throw special exception classes, like std::exception and derived from it.
Does throwing an exception in foo, terminate the foo function?
Yes, it does.
Are there cases where you could put the try and catch statements in the same function as the throw?
If you want, you can do that. There are not much cases where doing it is a good idea.
It looks like you need to get a good book and read chapter about exceptions. In the meantime this super-FAQ entry might help you/
You can throw an object of any type.
EDIT: (Hopefully I got this right now)
What you have done is throw a C-string, which is of type const char[13] in this case. C-Arrays will decay to pointers to their first element, in this case a pointer of type const char*.
Typically what you want to do is throw a predefined exception object. They can be found in header <stdexcept> and are derived from a base class std::exception. The derived exception classes are for instance std::logic_error, std::range_error, std::bad_alloc etc.
Their constructors take a string as argument, so you can for instance
throw std::logic_error{"Negative values not allowed."};
This message can be accessed in a catch statement like this:
catch(std::exception &e) // capture reference to base class
{
std::cout << e.what() << '\n'; // what() of derived is called, since virtual
}
If an exception is caught, so-called stack unwinding takes place. You can then deal with the error locally, or rethrow the exception. Only when an exception is thrown and never caught, std::terminate() is called an the program aborted.
You can put try/catch statements anywhere. However, remember what the term "exception" actually means. Cases that can easily dealt with using a simple conditional expression if (n < 0) break; or something like that, don't need the exception treatment. Especially if you can realistically expect this kind of unwanted condition to be true often. Then it is not something "exceptional".
If you decide to deal with an error using exceptions and they can not be treated locally, you may put try/catch clauses around the beginning and end of main().
Since you can put several catch statements directly after a try statement, you can then begin to deal with more specific errors, or simply catch anything via catch(...) { //... }.
This is all described in great detail (including pointers on when and when not to use it, in the C++ FAQ.
EDIT: Here's an example that makes use of try/catch statements. However, not an exception object is caught, but an int (errno). Just to show, that you can really throw/catch anything you like. Let process_several_files() be a function somewhere nested in your code:
std::vector<std::string> process_several_files(std::vector<std::string> const& files)
{
std::vector<std::string> contents{};
contents.reserve(files.size()); // files contains file names from user input
for (auto const& file : files)
{
try
{
contents.emplace_back(get_file_contents(file.c_str())); // A "C like" function. get_file_contents() will throw "errno", if a file does not exist
}
catch(int err)
{
std::cerr << "***Error while opening " << file << " : " << std::strerror(err) << "***\n";
continue; // "scope" didn't change, just keep iterating!
}
}
return contents;
}
can I get description of an exception caught by
catch(...)
block? something like .what() of std::exception.
There is one trick you might be able to use:
catch(...) {
handle_exception();
}
void handle_exception() {
try {
throw;
} catch (const std::exception &e) {
std::cout << e.what() << "\n";
} catch (const int i) {
std::cout << i << "\n";
} catch (const long l) {
std::cout << l << "\n";
} catch (const char *p) {
std::cout << p << "\n";
} catch (...) {
std::cout << "nope, sorry, I really have no clue what that is\n";
}
}
and so on, for as many different types as you think might be thrown. If you really know nothing about what might be thrown then even that second-to-last one is wrong, because somebody might throw a char* that doesn't point to a nul-terminated string.
It's generally a bad idea to throw anything that isn't a std::exception or derived class. The reason std::exception exists is to allow everybody to throw and catch objects that they can do something useful with. In a toy program where you just want to get out of there and can't even be bothered to include a standard header, OK, maybe throw an int or a string literal. I don't think I'd make that part of a formal interface. Any exceptions you throw are part of your formal interface, even if you somehow forgot to document them.
That block might catch an int, or a const char*, or anything. How can the compiler possibly know how to describe something when it knows nothing about it? If you want to get information off an exception, you must know the type.
If you know you only throw std::exception or subclasses, try
catch(std::exception& e) {...e.what()... }
Otherwise, as DeadMG wrote, since you can throw (almost) everything, you cannot assume anything about what you caught.
Normally catch(...) should only be used as the last defense when using badly written or documented external libraries. So you would use an hierarchy
catch(my::specialException& e) {
// I know what happened and can handle it
... handle special case
}
catch(my::otherSpecialException& e) {
// I know what happened and can handle it
... handle other special case
}
catch(std::exception& e) {
//I can at least do something with it
logger.out(e.what());
}
catch(...) {
// something happened that should not have
logger.out("oops");
}
Since C++11 you can capture the current exception with a pointer:
std::exception_ptr p; // default initialization is to nullptr
try {
throw 7;
}
catch(...)
{
p = std::current_exception();
}
This behaves like a smart pointer; so long as there is at least one pointer pointing to the exception object it is not destroyed.
Later (maybe even in a different function) you can take action in a similar way to the current top answer:
try {
if ( p )
std::rethrow_exception(p);
}
catch(int x)
{
}
catch(std::exception &y)
{
}
How we have our exceptions implemented is that, we have our own Exception classes, that are all derived from std::exception..
Our exceptions will contain Exception message, Function name, File name and line where exceptions are generated. These are all useful not just to show the Messages but also can be used for logging which helps to diagnose the Exception quite easily. So, we get the entire information about the Exceptions generated.
Remember exceptions are for us to get information about what went wrong. So, every bit of information helps in this regard..
Quoting bobah
#include <iostream>
#include <exception>
#include <typeinfo>
#include <stdexcept>
int main()
{
try {
throw ...; // throw something
}
catch(...)
{
std::exception_ptr p = std::current_exception();
std::clog <<(p ? p.__cxa_exception_type()->name() : "null") << std::endl;
}
return 1;
}
Is there any way to get at least some information inside of here?
...
catch(...)
{
std::cerr << "Unhandled exception" << std::endl;
}
I have this as a last resort around all my code. Would it be better to let it crash, because then I at least could get a crash report?
No, there isn't any way. Try making all your exception classes derive from one single class, like std::exception, and then catch that one.
You could rethrow in a nested try, though, in an attempt to figure out the type. But then you could aswell use a previous catch clause (and ... only as fall-back).
You can do this using gdb or another debugger. Tell the debugger to stop when any exception is throw (in gdb the command is hilariously catch throw). Then you will see not only the type of the exception, but where exactly it is coming from.
Another idea is to comment out the catch (...) and let your runtime terminate your application and hopefully tell you more about the exception.
Once you figure out what the exception is, you should try to replace or augment it with something that does derive from std::exception. Having to catch (...) at all is not great.
If you use GCC or Clang you can also try __cxa_current_exception_type()->name() to get the name of the current exception type.
Yes there is, but how useful it is is open to debate:
#include <exception>
#include <iostream>
using namespace std;
int f() {
throw "message";
}
int main() {
try {
f();
}
catch ( ... ) {
try {
throw;
}
catch( const char * s ) {
cout << "caught " << s << endl;
}
}
}
And to actually to answer your question, IMHO you should always have a catch(...) at
the top level of your code, that terminates (or otherwise handles) when presented with an unexpected exception in your application, in a manner fully documented by your application's manual.
I believe you should catch (...), if you have a reasonable course of action at that point and want the application to keep running.
You don't have to crash in order to generate a crash report, mind you. There's API for generating a mini-dump and you can do it in your SEH handler.
here's an approach I used on one project. it involves rethrowing until an exception type is matched against a list of known exceptions and then dispatching some action upon a match (in this case just returning some string information, but it could also be calling a registered function object).
This idea can be extended into a dynamic registry of exception types if you wish, the thing you have to be careful of is to ensure that the list is in most-derived to least-derived order (requires a lot of rethrowing and catching during registration!)
#include <iostream>
#include <stdexcept>
#include <exception>
#include <typeinfo>
#include <system_error>
namespace detail {
// a function which compares the current exception against a list of exception types terminated
// with a void type
// if a match is made, return the exception (mangled) class name and the what() string.
// note that base classes will be caught if the actual class is not mentioned in the list
// and the list must be in the order of most-derived to least derived
//
template<class E, class...Rest>
std::string catcher_impl()
{
try
{
std::rethrow_exception(std::current_exception());
}
catch(const E& e)
{
bool is_exact = typeid(E) == typeid(e);
return std::string(typeid(E).name()) + (is_exact ? "(exact)" : "(base class)") + " : " + e.what();
}
catch(...)
{
return catcher_impl<Rest...>();
}
return "unknown";
}
// specialise for end of list condition
template<> std::string catcher_impl<void>()
{
return "unknown exception";
}
}
// catcher interface
template<class...Es>
std::string catcher()
{
return detail::catcher_impl<Es..., void>();
}
// throw some exception type
// and then attempt to identify it using the type list available
//
template<class E>
void test(E&& ex)
{
try
{
throw std::forward<E>(ex);
}
catch(...)
{
std::cout << "exception is: "
<< catcher<std::invalid_argument, std::system_error, std::runtime_error, std::logic_error>()
<< std::endl;
}
}
int main()
{
test(std::runtime_error("hello world"));
test(std::logic_error("my logic error"));
test(std::system_error(std::make_error_code(std::errc::filename_too_long)));
test(std::invalid_argument("i don't like arguments"));
struct my_runtime_error : std::runtime_error
{
using std::runtime_error::runtime_error;
};
test(my_runtime_error("an unlisted error"));
}
example output:
exception is: St13runtime_error(exact) : hello world
exception is: St11logic_error(exact) : my logic error
exception is: NSt3__112system_errorE(exact) : File name too long
exception is: St16invalid_argument(exact) : i don't like arguments
exception is: St13runtime_error(base class) : an unlisted error