C++ error number allocation - are there any accepted standards? - c++

Are there any conventions about which error numbers I should use in my C++ code?
Do I start at 1 or should I pick a high number and go from there?
An example was requested, so here it is:
#define ERR_EVERYTHING_IS_WRONG 42
try
{
throw ERR_EVERYTHING_IS_WRONG;
}
catch(int err)
{
//
}

For try-catch, do not use numbers! Use a class derived from a standard exception class. Example:
#include <stdexcept>
class my_error : public std::runtime_error {
public:
explicit my_error(const std::string& what_arg) : std::runtime_error(what_arg) {};
};
Usage (Coliru):
#include <iostream>
int main() {
try {
throw my_error("You can even pass a string here!");
} catch (const my_error& e) {
std::cerr << e.what();
}
}
Or simpler: use std::runtime_error
#include <stdexcept>
#include <iostream>
int main() {
try {
throw std::runtime_error("Error happened");
} catch (const std::runtime_error& e) {
std::cerr << e.what();
}
}
Without standard library:
class my_error {
};
int main() {
try {
throw my_error();
} catch (const my_error& e) {
//TODO handle my_error
}
}

One of the best way is to follow standard for conventions of different errors in C++ codes is Enum
eg:
enum FILE_ERROR{
FILE_NOT_FOUND,
FILE_NO_ACCESS,
FILE_BUSY
};
so in code u can use FILE_NOT_FOUND as error number which is 0 . So this makes easy to understand what error type stands for what

There is no rule, you can do whatever you want as long as you keep a logical way to assign it.
If you choose 3 for bad user input, keep it for only that error or you'll get lost really soon

In C++ it is common to have 1 as success and 0 as error code, unlikely to C, where there are many functions returning 0 as success (strcmp, etc...)
this may be confusing sometimes, especially when interacting with C code, however I find that it helps a lot readability.
if(cplusplus_function()) {...}
is a lot more readable than
if(!c_function()){ ... }
remember also that you have exceptions to leverage in C++, and try to avoid nesting if-s

You don't "throw" any number, you "throw" an exception, an object of a class that derives from std::exception.
Standard exceptions contain text, and do not actually contain an error number. You can however create different classes for different types of exceptions, and have different catch handlers dependent on which exception type was thrown.

Related

Defining exception classes

I'm wondering if it's generally a good practice to define your own exception classes for a given program. For example, I have a program that mainly does reading from/writing to files, and modifying iptables rules. I've written the program its own basic logger class as well. To handle unexpected values or errors such as opening files, I typically use std::runtime_error. I am wondering if defining my own exception classes is generally a good idea. Example:
void Protocol::set_port(const unsigned long &port) {
if ( (port > 0) && (port < 65535) ) {
port_ = port;
}
else {
throw std::invalid_argument("Invalid port number");
}
}
I don't like using a whole bunch of try and catch blocks, since I find it to be a bad and ugly practice (although I may be wrong).
I'm wondering if it's generally a good practice to define your own exception classes for a given program.
Yes, in general the exception's type should be descriptive of the source or cause, so you can handle that particular exception through pattern-matching rather than code.
I typically use std::runtime_error. I am wondering if defining my own exception classes is generally a good idea.
Yes, in general you should follow these rules:
Obviously, only use exceptions to report exceptional failures (i.e. a precondition not being met, or a resource being unavailable for reasons beyond your program's incorrect operation).
If the failure is a logical error (the caller is trying to do something illegal within your program's domain) then derive your exception from std::logic_error.
If the failure is a result of an invalid argument, then it would make sense to derived from std::invalid_argument.
If the failure is a runtime error (e.g. file missing) then derived from std::runtime_error.
It can also be useful to nest exceptions, since you can then pass both a summary and a cause of the exception for later diagnosis, example:
 
struct port_out_of_range : std::invalid_argument
{
port_out_of_range(std::string const& context, unsigned long given)
: std::invalid_argument(context + ": port given: " + std::to_string(given))
{
}
};
void Protocol::set_port(const unsigned long &port)
{
if ( port < 65535 ) {
port_ = port;
}
else {
throw port_out_of_range("Protocol::set_port", port);
}
}
... later ...
try {
// ... some things ...
foo.set_port(x);
// ... more things ...
}
catch(port_out_of_range& e)
{
// maybe some remedial action possible here
}
catch(std::exception& e)
{
// but not here
log(e);
throw;
}

How to use BOOST_THROW_EXCEPTION correctly?

I try to use boost exceptions and fall.
There are the problem code:
struct exception_base : virtual std::exception, virtual boost::exception
{
exception_base(std::exception&& e)
: std::exception(e)
{}
};
int main()
{
std::string exception_description;
try
{
BOOST_THROW_EXCEPTION(exception_base(std::runtime_error("hello exception")));
}
catch (exception_base& ex)
{
exception_description = boost::diagnostic_information(ex);
}
return 0;
}
In this case the value of the exception_description have the last string - "std::exception::what: Unknown exception". It is unexpected value. If I change BOOST_THROW_EXCEPTION to usual throw - the last string of exception_description value looks expected - "std::exception::what: hello exception"
So how to use BOOST_THROW_EXCEPTION correctly?
Your custom exception class is not necessary, and is the root cause of your problems. If you remove it you can just do this:
BOOST_THROW_EXCEPTION(std::runtime_error("hello exception"));
Then:
catch (const std::exception& ex)
And the code will work the way you expect.
Why was it not working before? Well, your exception_base class has no storage for the error message, so when you construct it from a std::exception it cannot store the message (e.g. from the original runtime_error).
You could fix it a lot of different ways, but ultimately they will boil down to the same thing: if you want your custom exception class to contain a message string, it must somehow contain that message string.
I'm a fan of not defining custom exception types 95% of the time, so I'd advise you to just keep it simple and use runtime_error (and/or logic_error).
Note that BOOST_THROW_EXCEPTION automatically adds boost::exception as a base class for the thrown type, so you do not need to do that yourself anyway--there's no advantage.
other things:
at your catch site use std::cerr << boost::diagnostic_information(ex) << std::endl; and that will print all the metadata that BOOST_THROW_EXCEPTION adds on like: file, line, function, etc
if you are throwing a std::exception inside of the BOOST_THROW_EXCEPTION() you can wrap your std::exception with boost::enable_error_info() to change the type to boost::exception and that allows you to enrich the exception with other arbitrary fields via operator<<

Is it clean code?

#include <fstream>
#include <iostream>
#include <stdexcept>
using namespace std;
class FileNotFound: public logic_error
{
public:
explicit FileNotFound(const string& _Message):logic_error(_Message){}
};
int main()
{
try
{
ifstream file;
file.open("NoExistingFile");
if (file.fail())
throw FileNotFound("");
}
catch(const FileNotFound &e)
{
cout << "FileNotFound" << e.what();
}
catch(const exception &e)
{
cout << e.what();
}
return 0;
}
Output: FileNotFound
Is it Clean code (Robert Martin)?
std::exception not provide "location of an error".
Clean Code A Handbook of Agile Software Craftsmanship (Robert Martin) -> Chapter 7: Error Handling -> Provide Context with Exceptions
Considering the quoted paragraph, it is certainly not clean, because you just get the information of what happened, but you do not get the information from where the exception was thrown, therefore you can not trace it back for debugging.
Instead of using standard exceptions, I would advise to use boost exceptions, since they can provide the context from where the exception is thrown.
The more fundamental question is: Why use an exception in the first place? If it's a non-exceptional behavior (if it can be expected that a file might not be present), than no exception should be thrown at all. Instead control should flow along an "official path".
Add-on: It is not clean in the sense of the quoted book section (because the context needed to locate the problem is not provided with the exception -as others have mentioned) but also because:
The custom exception is used to manipulate control flow.
So instead of :
throw FileNotFound("");
}
catch(const FileNotFound &e)
{
Do only:
cout << "FileNotFound" << e.what();
The variable name 'e' is not really self explanatory and should also not be repeated.
The exception class should have its own file.
You should not use error and exception interchangably (in your question). This is an extra tipp imho.

why try...catch requires EXACT type thrown

I can do this, no problem:
long lngval = 3L;
int i = lngval;
but if I try this:
try {
throw 3L;
}
catch(int i) {
cout << "caught " << i << endl;
}
I get an unhandled exception.
This seems inconsistent. what is the reason for no type conversion in this case?
In the first case, the compiler can tell exactly what you want to do: convert a long to an int. In the second case, the compiler has to assume that you might have a construct like this:
try {
try {
throw 3L;
}
catch (int i) { /* P */ }
}
catch (long l) { /* Q */ }
The idea is that the compiler can never know whether there might be a catch (long l) lurking outside the current context, so it's never safe to just pick the first possible conversion.
This is also why it's common to use a class hierarchy when throwing exceptions rather than random types like int or long: it makes it easy to add more or less specification to your exception handlers in such a way that the compiler can be sure of your intentions (via the is-a relationship).
catch does not necessarily need the exact type.
It is common and good practice to use exceptions derived from std::exception (found in <stdexcept>). The reason is that you can then catch polymorphically, i.e. you do not need to know the exact type (see also Difference: std::runtime_error vs std::exception()) and that we have a convention to handle this.
Either you use one of the ones provided by the standard (e.g. std::range_error), or if nothing suits your problems [enough], specialize std::exception:
#include <stdexcept>
class moores_law_stopped : public std::exception {
public:
virtual ~moores_law_stopped() throw() {}
virtual const char *what() const throw() {
return "moores law stopped. duck under your table.";
}
};
#include <iostream>
int main () {
try {
throw moores_law_stopped();
} catch (std::exception const &e) {
std::cerr << "oh oh: " << e.what() << std::endl;
}
}
Output:
oh oh: moores law stopped. duck under your table.
The convention is to catch by reference or const reference, so that you get polymorphic behavior without fearing object slicing.
The catch statement catches an object (or a scalar variable in your cases) given its type, so if the type mismatch, it passes to the next catch statement (if there is one) or to the default exception receiver.
In your case, you could have a second catch statement catching long, and maybe somewhere else, so your catch statement won't catch anything.
To catch any exception, just use catch() {} :)
A single tip, better use exception class, or subclass it for you own need :)
You can also throw 3; - no problem.
int and long are different types. It's an advantage of the exception handling that you can tell the exceptions apart from looking at their type (one central try block can handle exceptions of various kinds from various places / a try block can handle just some kinds of exceptions, letting others propagate).
Also, it is recommended to throw one of the standard exceptions or derive a class from one of those. Then you could just catch (const std::exception&) if you just want to handle the exception and don't care about the particular type.
You can catch multiple types in one try-catch block. In order for the compiler to know which catch block to throw to, it must be able to match the exact type. Or it can have a default catch block -- catch (...) {}, but you won't be able to get at the value thrown in that case.

Code reuse in exception handling

I'm developing a C api for some functionality written in C++ and I want to make sure that no exceptions are propagated out of any of the exported C functions.
The simple way to do it is making sure each exported function is contained in a:
try {
// Do the actual code
} catch (...) {
return ERROR_UNHANDLED_EXCEPTION;
}
Let's say I know one exception that is often missed inside the C++ code is std::bad_alloc and I want to treat it specially I'd write something like this instead:
try {
// Run the actual code
} catch (std::bad_alloc& e) {
return ERROR_BAD_ALLOC;
} catch (...) {
return ERROR_UNHANDLED_EXCEPTION;
}
Is it possible to decompose this in some clever way so that I can globally treat some errors differently without adding a new catch statement for the exception handler around every exported function?
I'm aware of that this is possible to solve using the preprocessor, but before going down that road, I'd make sure there is no other way to do it.
You can use only one handler function for all possible exceptions, and call it from each or your API implementation functions, as below:
int HandleException()
{
try
{
throw;
}
// TODO: add more types of exceptions
catch( std::bad_alloc & )
{
return ERROR_BAD_ALLOC;
}
catch( ... )
{
return ERROR_UNHANDLED_EXCEPTION;
}
}
And in each exported function:
try
{
...
}
catch( ... )
{
return HandleException();
}
There already is a good answer. But just FYI, its called 'exception-dispatcher' idiom, see C++ FAQ.
What about:
try{
//Your code here
} catch(std::exception e)
{
return translateExceptionToErrorCode(e);
} catch(...)
{
return UNKNOWN_EXCEPTION_THROWN;
}
Jem answer is a little more simpler than this solution. But it is possible to substitute the use of a preprocessor macro with the use of templates. Something like this (more refinements you could made):
template <class T, void (T::*FUNC)()>
class CatchWrapper
{
public:
static void WrapCall(T* instance)
{
try
{
(instance->*FUNC)();
}
catch (std::bad_alloc&)
{
// Do Something 1
}
catch (std::exception& e)
{
// Do Something 2
}
catch (...)
{
// Do Something 3
}
}
};
class Foo
{
public:
void SomeCall()
{
std::cout << "Do Something" << std::endl;
}
};
int main(int argc, char* argv[])
{
Foo i;
CatchWrapper<Foo, &Foo::SomeCall>::WrapCall(&i);
return 0;
}
Do not ever use catch(...), unless you plan on more or less immediately re-throwing. You will certainly lost any error information you might have had to help you figure out the cause of the error.
I like your second scheme a little better - catch a known set of exceptions, ideally because they are the only ones your code will throw, and let the rest through - allowing the app to crash is possibly the best thing to do since you have invoked unknown behaviour it is best to "crash responsibly".
It would be a shame to loose error information at the language boundary. You really should try to translate all exceptions into an error code usable from C.
How you do it really depends on what your exception classes look like. If you control your exception class hierarchy, you can ensure that each class provides a translation using a virtual method. If not, you may still find it practical to use a translator function and test the types of the 'std::exception'-derived exception it receives to translate it into an error code, much like Jem suggested (remember: thrown exceptions will hurt performance anyway, so don't worry about the translation being slow).