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.
Related
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!
This question is similar to c++ Exception Class Design and follows:
I want to design exception class hierarchy for my application and here are the design points I used:
Exception should be derived from standard exception classes (those are std::exception, std::logic_error and std::runtime_error).
Exception class should be able to take error description (i.e. what is called what) and position where it occurred (const std::string &file, int line)
Exception should not throw any exception during construction or from any other member.
Given this I have:
#define throw_line(TException, what) throw TException((what), __FILE__, __LINE__)
class AnException : public std::exception {
public:
AnException(const std::string &what, const std::string &file, int line) noexcept {
try {
what_ = what;
file_ = file;
line_ = line;
} catch (std::exception &e) {
was_exception_ = true;
}
}
virtual ~AnException() noexcept {}
virtual const char *what() const noexcept override {
if (was_exception_) {
return "Exception occurred while construct this exception. No further information is available."
} else {
try {
std::string message = what_ + " at " + file_ + ":" + std::to_string(line);
return message.c_str();
} catch (std::exception &e) {
return "Exception occurred while construct this exception. No further information is available."
}
}
}
};
class ParticularException : public AnException {
...
}
As you can see, it appears to be somewhat complex to construct such class, because we definitely should not have exceptions in constructor (otherwise std::terminate() will be called) or in what() member.
The question: is this example of a good design or I should remove some restrictions (like, having file/line information) to simplify it? Is there a better way?
I'm free to use C++11/C++14, but trying to keep off C++17 since it is not yet finished and compilers may not fully implement it.
Note: I want this code to be cross-platform.
Thanks in advance.
Edit 1: The follow up question: how can I retire file/line information, but keep that in logs? May be printing stacktrace is a better solution than what I have now? I mean leave exception class which just holds an error message (what) and call something like print_backtrace on upper level of exception handling chain.
Relating to my comment, depending on whether a what literal is acceptable, I had something like this in mind:
#include <array>
template <int N> constexpr std::size_t arraySize(const char (&)[N]){return N;}
template <class ExceptT, std::size_t whatN, std::size_t fileN>
class MyExcept : public ExceptT
{
static_assert(std::is_base_of<std::exception, ExceptT>::value, "bad not base");
public:
MyExcept(
const char (&what)[whatN],
const char (&file)[fileN],
int line) noexcept
: ExceptT(""), //Using our own what
what_(), file_(), line_(line)
{
std::copy(std::begin(what), std::end(what), begin(what_));
std::copy(std::begin(file), std::end(file), begin(file_));
}
virtual const char *what() const noexcept override
{
//....
}
private:
std::array<char,whatN> what_;
std::array<char,fileN> file_;
int line_;
};
#define throw_line(TException, what) throw MyExcept<TException,arraySize(what),arraySize(__FILE__)>(what,__FILE__, __LINE__)
void driver()
{
throw_line(std::runtime_error, "Hoo hah");
}
I've added some code that allows deriving from a std::exception type (type requires constructor with single literal argument (could check that this is also noexcept). I'm passing it an empty string literal, so std::exception class should at least not throw. I'm using static_assert to check this.
it cannot throw on construction...
it derives from std::exception...
it contains "fixed" what and position
This usually happens only, if you want to catch certain errors in another catch-block than your most outer catch block. I would only start doing this, if I see a demand. I remember that my system-call-read() wrapper would throw a different exception for EOF -- since this sometimes need to be caught.
Then I've got a system-error-exception and a normal message exception, since std::exception does not store any message with certain compilers.
Separate classes for exceptions are overused in the same way throw-specifications were overused.
Please remember that if you want to catch a certain error somewhere else than in the outer-most-catch-block, you need to be able to do something about the error, other than re-throw it. Usually the string returned from what() should already be sufficient to tell you what kind of error occurred. Thus for printing reasons there is no need to overload the exception type.
So i have FRead function that reads data from file. I need to finish the program if the function returns error codes. Is it acceptable to do it like this:
string check=FRead(vec);
And then put some if statements that finish the program if check has certain values.
It is the only instance in program when i call the function and obviously i can't call it many times. It seems to work alright, but i'm not quite sure if it is the right way. So is there a proper way to do what i'm trying to do?
And i also have the KRead function reading input from keyboard, which too returns an error code if things go wrong. And i call it like this
if(KRead=='ERROR')
return 1
Is it okay to do so?
It is always better to use error codes or exceptions. The choice between both depends on the implementation. I made a few example applications that explain in general what string errors, error codes and exceptions are.
String errors
This will work but it's ugly, also you don't know what errors there are defined without disecting the GenerateError() function).
#include <string>
#include <iostream>
class Example
{
public:
std::string GenerateError(bool error)
{
if (error)
{
return "ERROR";
}
return "OK";
};
};
int main()
{
Example example;
if ("ERROR" == example.GenerateError(true))
{
return 1; // failure
}
return 0; // success
}
Error Codes
With an enum you specify which error codes are available (in this case Ok, Error and Error2). This makes the code easier to understand and it will save you from mistakes. With enums you can also make use of switch.
#include <string>
#include <iostream>
enum ErrorCodes
{
Ok = 0,
Error,
Error2
//...
};
class Example
{
public:
ErrorCodes GenerateError(bool error)
{
if (error)
{
return ErrorCodes::Error;
}
return ErrorCodes::Ok;
};
};
int main()
{
Example example;
// Regular if statement
if (ErrorCodes::Ok == example.GenerateError(true))
{
return 1; // failure
}
else
{
return 0; // success
}
// switch statement
switch (example.GenerateError(true))
{
case Error:
case Error2:
return 1; // failure
break;
case Ok:
return 0; // success
break;
}
return 0;
}
Exceptions
Exceptions are a bit more complex but are definitely worth it to check out. Use exceptions when you want to obligate the user of the function to do something with the error. When the function does not require an action on an error it's probably better to use error codes.
#include <string>
#include <iostream>
class CustomException :public std::exception{
public:
CustomException(const std::string m) :strMessage(m){}
~CustomException(void);
const char* what(){ return strMessage.c_str(); }
private:
std::string strMessage;
};
class Example
{
public:
void GenerateError(bool error)
{
if (error)
{
throw CustomException("Critical error");
}
return;
};
};
int main()
{
Example example;
try
{
example.GenerateError(true);
}
catch (CustomException ce)
{
std::cerr << ce.what() << std::endl;
return 1; // failure
}
return 0; // success
}
A good way to handle error conditions in C++ is to have your function throw exceptions if something goes wrong. You can then check for exceptions when you call it. See http://www.cplusplus.com/doc/tutorial/exceptions/.
This is perfectly fine. Like others have said though, you can use error codes instead of strings.
In case dynamic_cast<SomeType&> fails bad_cast exception is thrown. In my code there's a separate hierarchy of exceptions and bad_cast is not in that hierarchy so my code won't handle bad_cast. May I have some other exception thrown instead?
I mean I'd like to write a custom handler like this:
void OnBadCast()
{
throw MyException( "Bad cast" );
}
and somehow register it in C++ runtime
RegisterMyBadCastHandler( &OnBadCast );
so that this handler is invoked instead of bad_cast being thrown.
Is that possible?
I don't think you can change this behaviour.
What you could do, is use your own caster, however:
template<class T, class E> T myCast(E expr)
{
try
{
return dynamic_cast<T>(expr);
}
catch(std::bad_cast e)
{
// custom handler
}
};
Bad casts usually indicate a bug in the program (like eg. out of range, or out of memory), and thus should not be caught at all (or perhaps at the top-level). If you want to branch upon the success of dynamic_cast, then test for null in the pointer form:
if (T* p = dynamic_cast<T*>(some_ptr))
{
// Do something with p
}
If you want a special handler, the best you can do is thus the following:
template <typename T, typename U>
T& polymorphic_cast(U& x)
{
if (T* p = dynamic_cast<T*>(&x)) return *p;
my_handler();
}
where my_handler is supposed to kill the program (and perhaps log the error). But here, you may prefer using the plain dynamic_cast<T&> form, let std::bad_cast bubble up and be logged at the top level. This also plays better with debuggers, which can be set up to stop at the point where the cast fails.
Cases like you describe in your comments are rare enough to warrant special consideration, eg.:
if (auto p = dynamic_cast<foo*>(q)) { do_something(); }
else { throw bail_me_out_of_here(); }
may be used to indicate some upstream strategist that it should try another method.
You do not need to have exceptions in the same hierarchy to handle them. At least not in VC++. If you are just worried about handling different types of errors, do something like the below. If this answer does not suffice, the others are excellent considering the limitations you are working with, although take note of when bad_cast is thrown and when it is not. http://answers.yahoo.com/question/index?qid=20071106101012AAggZAk
#include <iostream>
#include <exception>
using namespace std;
class my_exception {
public:
explicit my_exception() {};
const char* msg() const { return "my_exception"; }
};
int main()
{
try {
// comment either line.
throw std::exception("std::exception");
throw my_exception();
}
catch (const std::exception& e )
{
cout << e.what() << endl;
}
catch (const my_exception& e)
{
cout << e.msg() << endl;
}
return 0;
}
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