I've written a function that uses Armadillo svd_econ function. I'm trying to handle the case where the svd fails to converge, because for some reason it doesn't abort the function in that case.
The error in question reads:
error: svd_econ(): failed to converge
Based on my reading of the SVD documentation, this should throw a std::runtime_error, and based on my reading of the Exceptions tutorial, I should be able to handle it like so:
arma::mat U, V;
arma::vec S;
try {
// aDat and subsetRows are previously defined
arma::svd_econ(U, S, V, aDat.rows(subsetRows), "right", "dc");
} catch (std::runtime_error e) {
std::cout << "Exception caught!" << std::endl;
// I want to abort, and return the error to R:
throw Rcpp::exception(e.what());
}
However, when I run this code with a case that gives me the error message above, I get a segfault. If I remove the try-catch block, the code keeps going, and throws an error further down when the code tries to use the results of the SVD.
I assume I'm just missing something obvious since I haven't formally learnt any C++
Looks good, I'd just try a few things:
a reference to the exception,
just error forwarding to R, not another throw(),
a default block with Rf_error()
So maybe (untested)
try {
arma::svd_econ(U, S, V, aDat.rows(subsetRows), "right", "dc");
} catch (std::runtime_error & e) {
std::cout << "Exception caught!" << std::endl;
forward_exception_to_r(e);
} default(...) {
Rf_error("Unknown exception");
}
but in essence you get all this for free via Rcpp Attributes as this is what the (automatically inserted) END_RCPP macro does --- see Section 2.7 of the Rcpp book for more details.
Edit But #mtall, in his comment, does what we should have done first: check the Armadillo docs. So you can simply check the return value. But you may want to try the suggested try/catch as well.
Related
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?
I'm working on exception handling and right now I'm stuck on a problem I'm working on out of my book. What I'm trying to do is add an try-catch block inside my main function to catch an exception that is thrown by a function that I am using. Here are snippets of where I am having trouble on.
EmptyStackPopException is an empty Exception class that I put into my stack.h file that can be seen here:
class EmptyStackPopException {
};
Here is the function that is supposed to throw this Exception.
T Stack<T>::pop( ) throw (EmptyStackPopException)
{
if (isEmpty( ))
{
throw EmptyStackPopException();
}
T result = top->getData( );
Node<T> *discard;
discard = top;
top = top->getLink( );
delete discard;
return result;
}
Here is a snippet of my main function where the exception is supposed to be caught:
try {
cout << s.pop( );
} catch (EmptyStackPopException) {
cout << "EmptyStackPopException: You didn't enter anything in." << endl;
}
Now the issue that I'm having is I cannot compile because of these following errors:
..\assignment8\main.cpp(29) : error C2061: syntax error : identifier 'EmptyStackPopException'
..\assignment8\main.cpp(29) : error C2310: catch handlers must specify one type
..\assignment8\main.cpp(32) : error C2317: 'try' block starting on line '27' has no catch handlers
I'm pretty sure that the only error I have at the moment is in the main function, EmptyStackPopException is not able to be detected in the client program which causes the last two errors.
You must specify a type with your catch statement. This should fix the three syntax errors your presented
try {
cout << s.pop( );
} catch (EmptyStackPopException& exception) {
cout << "EmptyStackPopException: You didn't enter anything in." << endl;
}
You needed to create 'exception'.
If including your EmptyStackPopException header doesn't work (based on context I'm not sure it will), the problem might be based on circular dependency, which means that two header files are including each other. I can't tell from context but this sometimes gives me the "syntax error : identifier" error.
Let's say I have a function (mnHw) that calculates the mean of a vector (a vector of homework grades). This function throws a domain_error("Student did no homework") exception when the vector is empty. When I call mnHw from main, things are simple when I want to print out the error:
try
{
cout << mnHw(student.homework);
}
catch (domain_error e)
{
cout << e.what();
}
However, things are complicated if I only want to store the mean homework grade, instead of vector of all grades, for the student. In that case I call mnHw within the function that reads in the student information (readStudent), and put up a flag (-1) when no homework is entered:
try
{
student.finalGrade=mnHw(hwGrades);
}
catch (domain_error e)
{
student.finalGrade = -1;
}
Then, within main, I can do the following to recover the error:
if (allStudents[i].finalGrade == -1)
cout << "Student did no homework";
else
cout << allStudents[i].finalGrade;
Intuitively, though, this flag method seems less elegant than having the actual error message pass directly to main, at least for those cases when I want to display it from main (which is the case here). Is there some trick or technique I am missing that would directly give main access to e.what() from mnHw?
What is good practice?
Note I have full functions for each of these cases that I could post, but they seemed too long. Please let me know if I should have included them to make myself more clear. Also, please feel free to correct any other mistakes I’m making. I am just now learning C++ the right way, and want to be corrected as much as possible. <flame-retardant vest>
You can re-throw the exception catched (const domain_error* e){ throw e;}. Or better, you can create based on domain_error create another exception i.e., student_final_grade_exceptionand throw it.
EDIT:
Something like:
try
{
student.finalGrade=mnHw(hwGrades);
}
catch (domain_error& e)
{
student_final_grade_exception mean_excep;
mean_excep.addInfo("Error in calculation means...");
mean_excep.addInfo(e.what());
throw mean_excep;
}
And then, you prepare your main to catch student_final_grade_exception. Of course, there is a litle bit more work to create a new exception type, but it can make possible to get more info and let the functions to only what they suppose to do as were told.
#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.
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).