#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.
Related
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<<
I'm using sqlite3pp to manipulate database. When I tried to insert one record twice in the same table by running,
sqlite3pp::command cmd(db, "INSERT INTO Groups (Name) VALUES (?)");
cmd.binder() << "Group_one";
cmd.execute();
it throwed an excpetion and showed me this:
libc++abi.dylib: terminating with uncaught exception of type
sqlite3pp::database_error: UNIQUE constraint failed: Groups.Name
But I'm not sure what type of exception should I use to catch? I tried
try {
cmd.execute();
} catch (std::exception& ex) {}
or
try {
cmd.execute();
} catch (sqlite3pp::database_error& ex) {}
or
try {
cmd.execute();
} catch (...) {}
But none of them work. Can anyone help me here? Thanks!
Here is my code:
#include <iostream>
#include "sqlite3pp.h"
int main(int argc, const char * argv[]) {
sqlite3pp::database db("./test.db");
// Create table
db.execute("CREATE TABLE IF NOT EXISTS Groups(" \
"Name TEXT PRIMARY KEY)");
sqlite3pp::command cmd(db, "INSERT INTO Groups (Name) VALUES (?)");
cmd.binder() << "Group_one";
try {
cmd.execute(); // When I run this code twice, the exception is thrown because of UNIQUE constraint.
} catch (std::exception& ex) {
std::cout << "exception: " << ex.what() << std::endl;
}
std::cout << "Done" << std::endl;
return 0;
}
I'm the writer of sqlite3pp and sorry for confusing you.
When I wrote this, I tried to make it very light weight. So, I decided not to translate all the sqlite3 error codes into c++ exceptions.
So, as a result, the methods have the integer type return value, which is the exact same error code that sqlite3 methods return. So, in this case, you need to check the return value of execute().
But, in some places, it cannot return the error code. e.g. in ctor and dtor. For these places, I introduced the database_error exception.
I would try to catch the exception type of the message ...
catch (sqlite3pp::database_error& ex)
{
...
}
I've look into the code and in the tests the developers use code like this:
#include "sqlite3pp.h"
try
{
sqlite3pp::command cmd(...);
cmd.execute();
}
catch (exception& ex) { // Note they use a reference here "exception&"
cout << ex.what() << endl;
}
so, you should use the same, if that doesn't work either, try to catch all using:
try {
cmd.execute();
} catch (...) {} // Using the ... should fix the error, but I recomend you to find the correct exception you have to catch.
Looking at the code closer
I have found the class (in sqlite3pp.h):
class database_error : public std::runtime_error
{
public:
explicit database_error(char const* msg);
explicit database_error(database& db);
};
So you should solve the problem using:
try {
cmd.execute();
} catch (database_error &e) {}
I was having this same issue - could not catch the exception no matter what I tried. However, after some digging I found out that C++11 declares destructors to be noexcept by default. I am using C++11 and was able to "fix" the issue by making the following change to the sqlite3pp code:
~transaction() noexcept(false);
transaction::~transaction() noexcept(false)
So, perhaps this is the issue the OP had?
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.
I have read answers to following questions ->
c++ exception : throwing std::string
c++ Exception Class Design
My requirement is to catch exceptions and allow a mechanism to reformat the error messages and then re-throw the exceptions.
So I thought of writing my exception class which will provide a method to reformat the error message at various catch points.To make reformatting easy, I'm embedding a string object in myexception_base class.
I have also referred to this article -> http://www.boost.org/community/error_handling.html which clearly says not to embed string objects in exception classes.
The article also has a quote "Peter Dimov makes an excellent argument that the proper use of a what() string is to serve as a key into a table of error message formatters." but it does not elaborate on it any further.
I have written the code as given below and my questions are -
1) If I don't embed a string object in my exception class, it will make it difficult to reformat the what messages. Please tell me How shall I approach to my requirement without embedding a string object in my exception class?
2) If I carry on with my current approach of embedding a string object and providing a method to format error message. Is my way of handling some scenarios correct ? (Issue 1 and Issue 2 in which error msg doesn't get formatted)
Issue 1 - wrong exception getting propagated to catch points ?
Issue 2 - Error Message not getting formatted in some scenarios ?
Issue 1 and Issue 2 are mentioned in comments in code below.
Kindly have a look at the code. I have given lot of comments in code so lines of code has increased but if I remove the comments it has very less lines of code.
#include <string>
#include <exception>
#include <iostream>
using namespace std;
class myexception_base : public exception {
private:
string error_msg;
public:
myexception_base(const char* str) : error_msg(str) {
// std::string here here can throw an exception while error_msg
//initialisation through MIL.
// myexception_base object will not be constructed
// and wrong exception will be propagated to catch point(Issue 1)
}
const char* what() const throw() {
try {
return error_msg.c_str();
} catch (...) {}
// c_str can throw.
// I can't remove throw specification from what()
// because what() in base std::exception has throw() specification
// In case c_str() throws an exception program will terminate
// So to stop abnormal termination of program c_str
// is wrapped in a try catch block to ignore std::string exception
// program will not terminate but what message is not reformatted
// in such scenario (Issue 2)
}
void append_error_msg(const char* str) {
error_msg.append(str);
// append can throw
// Again error_msg will not be formatted (Issue 2)
}
~myexception_base() throw() {
}
};
void f();
void f2();
void f() {
throw myexception_base("Error Msg1");
}
void f2() {
//Some intermediate Catch point will reformat e.what() msg
//by appending an error msg2
try {
f();
}
catch (myexception_base& e) {
e.append_error_msg(": Error Msg2");
throw;
}
}
int main () {
try {
f2();
}
catch(const exception& e) {
// Finally the exception is caught in the upper most layer
// and proper error_msg is given to user
cout<<e.what()<<"\n";
}
}
According to the boost documentation embedding classes which might throw during their lifetime are not an excellent candidate to be used in the exception handler mechanism, so I would like to suggest that you will simply use the good old C way of handling strings. It will require some extra effort to bring it up and running but with them you have eliminated one source of error.
So, basically there are two approaches:
In the myexception_base you declare the error_msg as being an array of N chars. In the append_error_msg you carefully check that the length of the NEW string (after the append) is not greater than N and if it is not, then you use strcat or one of the other C string handling methods. This approach might be good, since it does not allow memory leaks through the exception handling mechanism, however you can have only a limited length of error message.
In the myexception_base you declare the error_msg as being a char* (a char pointer). In the constructor you callocmemory for it (do not use new since new might throw) and in the append_error_message you realloc the pointer to be the new size (ie. old size + string to be appended.size + 1 for the 0) and then memcpy to the requested position (ie. at the position of the end of the old string in the newly allocated string). Of course, do not forget to check all the allocations/re-allocations that they have returned a valid value otherwise you might get funny behavior. And last, but not least, to avoid the classical memory leaks, free the memory of the char* in the destructor.
Good luck!
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.