try catch blocks with boost.Test - c++

I have a (Class member) function which I wish to avoid app crash due to ambiguity. For that purpose I have added a try catch bock as shown below:
void getGene(unsigned int position){
T val;
try {
val = _genome.at(_isCircular ? position % _genome.size() : position);
}
catch (std::exception& e) {
std::cerr << "Error in [" << __PRETTY_FUNCTION__ << "]: "
<< e.what() << std::endl;
exit(1);
}
return val;
}
Now, I wish to add a Boost unit test, which I thought of doing something like
BOOST_AUTO_TEST_CASE(nonCircularGenome_test){
// set size to 10
test.setSize(10);
// set non circular
test.setNonCircular();
// gene at site # 12 does not exist in a 10-site long genome, must throw an exception
BOOST_CHECK_THROW(test.getGene(12), std::out_of_range);
The problem is, I can't get both these things work. The try-catch block works well in release setup. However, this test works, only if I remove the try-catch block and let the function throw the exception.
What is the best way to get both these things working, so that a user is prompted with correct error on the go, while tests check explicitly on debug? One way is the use #ifdef/#endif DEBUG blocks, but I wish to avoid pre-processor macros.
Thanks in advance,
Nikhil

You seem to be misunderstanding the scope and purpose of exceptions - and perhaps of error handling in general.
First of all, you should define what are the pre-conditions of your function: does getGene() always expect position to be a valid one? Does it expect its clients to never provide invalid positions?
If that is the case, a client that provides an invalid position (even if the client is a test routine) is breaking the contract with the getGene() (in particular, it is breaking its pre-condition), and breaking a contract is undefined behavior by definition. You cannot test undefined behavior, so you should remove your test.
On the other hand, if your function has a wide contract, i.e. it allows the clients to pass in any position (even invalid ones) and (a) throws an exception or (b) returns an error code to communicate failure when the position is invalid, then the exit(1) line should not be there, because you are quitting the program and control is not transferred back to the caller.
One possibility is to re-throw the exception after logging the diagnostic:
T getGene(unsigned int position){
T val;
try {
val = _genome.at(_isCircular ? position % _genome.size() : position);
}
catch (std::exception& e) {
std::cerr << "Error in [" << __PRETTY_FUNCTION__ << "]: "
<< e.what() << std::endl;
throw;
// ^^^^^
}
return val;
}
And if you do not need to print a diagnostic, just let the exception naturally propagate:
T getGene(unsigned int position){
return _genome.at(_isCircular ? position % _genome.size() : position);
}

Related

Best practices coding c++ [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
I'm wondering, is there a better way to write code when there are functions with status returns.
Below is an example. (Please ignore simple code errors if there are any. I'm specifically talking about the structure. Plus, I'm at work and don't have a compiler on this computer)
#include "Session.h"
Session::Session(const char * IPaddress, unsigned int openPort)
{
ssh_session mySession;
hostIP = IPaddress;
port = openPort;
}
int Session::cBeginSession()
{
try
{
int status = ssh_options_set(mySession, SSH_OPTIONS_HOST, &hostIP);
if (status == 0)
{
status = ssh_options_set(mySession, SSH_OPTIONS_LOG_VERBOSITY,
SSH_LOG_PROTOCOL);
if(status == 0)
{
status = ssh_options_set(mySession, SSH_OPTIONS_PORT, &port);
if (status == 0)
{
std::cout << "Session started\n";
return 0;
}
else
{
std::cout << "Unable to set port\n";
return -3;
}
}
else
{
std::cout << "Protocol option log verbosity unable to set\n";
return -2;
}
}
else
{
std::cout << "Unable to set Host address\n";
return -1;
}
}
catch (...)
{
std::cout << "Unknown exception occurred\n";
return -8;
}
}
I typically use if-else statements with the status parameters, but I tend to end up with large nests of if-else statements if there are more than one or two functions involved. Is there a more readable way to write something like this? It turns into a rats nest very quickly.
EDIT: Thank you for all the replies. I think I have some ideas of how to structure my code better. I appreciate all the diligent suggestions.
In modern C++ programming, typically, if you encounter an error where the program can't continue, then I think it's better to throw an exception.
So your function would wouldn't return anything (i.e. void). Whenever it ran into a can't continue situation, you would throw an exception that tells what the error is. The calling code would then deal with the error.
The advantage to this, is that you get to choose where to deal with the error. For example, the stack may unwind all the up to main.
You code could look like this:
void Session::cBeginSession()
{
if (ssh_options_set(mySession, SSH_OPTIONS_HOST, &hostIP))
{
// throw an exception
}
if (ssh_options_set(mySession, SSH_OPTIONS_LOG_VERBOSITY, SSH_LOG_PROTOCOL))
{
// throw an exception
}
if (ssh_options_set(mySession, SSH_OPTIONS_PORT, &port))
{
// throw an exception
}
}
Once you get the hang of coding with exceptions, code tends to be cleaner and more robust since you're not always worrying about checking return codes.
EDIT
To answer you comment. You can choose how and when to handle the error. You can just catch the exception above your call. But, in general, if you want to do something that can fail (but not end a program) you can make another function that returns a boolean status.
bool Session::tryCBeginSession()
Now, your original function void Session::cBeginSession() would be implemented in terms of this new function. I've found that in most cases writing these dual functions is done only in a limited number of cases.
I like to reduce nesting, like this:
status = fcn1();
if ( status == 0 )
{
// something good
status = fcn2();
}
else
{
// something bad happened. report, and leave status reporting failure.
}
if ( status == 0 )
{
// something good
status = fcn3();
}
else
{
// something bad happened. report, and leave status reporting failure.
}
if ( status == 0 )
{
// something good
status = fcn4();
}
else
{
// something bad happened. report, and leave status reporting failure.
}
I like that error printing is close to the error occurrence. Sure, when failure happens, the status gets checked extra times. But it's a small price to pay for the simplicity.
This also lends itself well to de-allocation of resources and closing files at the end, regardless of where the error occurs.
You don't need if-else if you either return or throw in the statement that follows (this is a good case for throwing BTW). Plain ifs will do.
The type of messages you're printing are usually better suited to stderr rather than stdout (cerr rather than cout).
If you decide you will keep using error statuses, symbolic constants (or enums or defines) are usually preferred over "magic numbers"
This is a pretty ideal scenario for exception-handling (at least how it was intended). Exception-handling is typically appropriate for handling external input errors, as in this case where the external input is coming from a socket.
You already have a try/catch block, but I would suggest eliminating it since there's no recovery code. Keep your try/catch blocks generally focused around areas where you make a change transaction. Catching an exception then rolls back the changes, gets the system back to a valid state, and possibly outputs some message.
Something like this:
void Session::cBeginSession()
{
if (ssh_options_set(mySession, SSH_OPTIONS_HOST, &hostIP) != 0)
throw runtime_error("Unable to set Host address");
if (ssh_options_set(mySession, SSH_OPTIONS_LOG_VERBOSITY, SSH_LOG_PROTOCOL) != 0)
throw runtime_error("Protocol option log verbosity unable to set.");
if (ssh_options_set(mySession, SSH_OPTIONS_PORT, &port) != 0)
throw runtime_error("Unable to set port");
std::cout << "Session started\n";
}
Let the client code calling this function catch the exception at a site where it's appropriate to handle and recover from the error. Just worry here about throwing the exception appropriately in the case of these external input errors.
Note that exception-handling is typically ultra cheap in the non-exceptional cases (where you don't throw) with optimizations like zero-cost EH. However, these kinds of exception-handling compiler optimizations make the rare case much slower where you actually do throw an exception. So exceptions should be used for truly exceptional cases resulting from some kind of external input your software can't normally handle, as in this case.
Another caveat relevant in certain types of larger systems (plugin architectures, e.g.), is that typically exceptions should not be thrown across module boundaries.
This is somewhat opinionated but I don't recommend having lots of catch branches based on the type of exception (as commonly found in Java, e.g.). Often there isn't a need to distinguish the actual type of an exception so much as relay a message to the user, e.g. Catch exceptions as generally/coarsely as you can, and keep the try/catch blocks to a minimum (high-level transaction-oriented mentality: transactions succeed as a whole or fail and roll back as a whole).
Otherwise exceptions can really simplify these kinds of cases, and a whole lot of the C++ library (and even parts of the language) throw exceptions normally (I really think C++ and exception-handling are inseparably tied), so it can be useful to make use of them since a robust program will typically need to generally catch them anyway.
In this particular case (error codes handling), I'm advocating for early returns:
int status = ssh_options_set(mySession, SSH_OPTIONS_HOST, &hostIP);
if (status != 0)
{
std::cout << "Unable to set Host address\n";
return -1;
}
status = ssh_options_set(mySession, SSH_OPTIONS_LOG_VERBOSITY,
SSH_LOG_PROTOCOL);
if (status != 0)
{
std::cout << "Protocol option log verbosity unable to set\n";
return -2;
}
status = ssh_options_set(mySession, SSH_OPTIONS_PORT, &port);
if (status != 0)
{
std::cout << "Unable to set port\n";
return -3;
}
std::cout << "Session started\n";
return 0;
I find the code much more readable because it has lest nesting and the error handling is kept close to the point where the error occured instead of being buried in a far else branch.
If you decide it is best to use exceptions rather than error codes, you can keep the same structure and replace returns with throws.
some suggestions noted in the code:
// improvement - derive your own descriptive exception FROM A STANDARD EXCEPTION TYPE
struct session_error : std::runtime_error
{
using std::runtime_error::runtime_error;
};
// improvement in constructor: initialiser lists
Session::Session(const char * IPaddress, unsigned int openPort)
: mySession()
, hostIP(IPaddress)
, port(openPort)
{
}
namespace {
// use of anonymous namespace so this wrapper function does not pollute other compilation units
void setopt(ssh_session& session, int opt, const void* val, const char* context)
{
if (ssh_options_set(session, opt, val))
throw session_error(context);
}
}
void Session::cBeginSession()
{
// improvement - defer to wrapper function that handles nasty return code logic
// and throws a sensible exception. Now your function is readable and succinct.
setopt(mySession, SSH_OPTIONS_HOST, &hostIP, "setting host option");
setopt(mySession, SSH_OPTIONS_LOG_VERBOSITY, SSH_LOG_PROTOCOL, "setting verbosity");
setopt(mySession, SSH_OPTIONS_PORT, &port, "can't set port");
std::cout << "Session started\n";
}

Mysterious segmentation fault on function return with no pointers or allocation involved

I am currently writing some C++ code that does a lot of text parsing. One feature pushes chars into a string after checking if the char is a visible char (as opposed to whitespace). However, when I run the code below:
void myWords::pushChar(char c){
myChar cc;
std::cout<< "before if" <<std::endl;
if(!(cc.isWS(c))){
std::cout<< "after if" <<std::endl;
myList.back();
}
else if((myList.back()).size()>0){
myList.push_back("");
}
}
Which calls the following code block:
bool myChar::isWS(char c){ // returns true if char is whitespace
std::cout<< "comparing" <<std::endl;
if((c >= '!') && (c <= '~')){
std::cout<< "compared" <<std::endl;
return false;
}
else {
std::cout<< "compared" <<std::endl;
return true;
}
}
When these functions run, I (sometimes) get a segmentation fault immediately after the "compared" is printed by myChar::isWS(). There are no pointers/dereferences in my code (although I assume C++ implements STL containers with some pointing behind the scenes), and there is no memory accessing at that point aside from the return call. I ran Valgrind with the code, which has told me that there is an invalid memory access taking place.
What types of things could cause this kind of issue with no pointers/dereferences? Is there some way I could have corrupted the stack with that code?
Thank you in advance for your help.
Your error looks like you are calling size on non-existent object returned when you have an empty list. I.e in the second if statement. You need to check for an empty list before you can use back () safely.
I am guessing you want to something like this
void myWords::pushChar(char c)
{
if( !isWhitespace (c) )
{
myList.push_back(c);
}
else
{
if( !myList.empty() && (myList.back().size()>0) ) // is last element a non-empty string ?
{
myList.push_back(""); // then push an empty string on to list
}
}
}
It would be helpful to know how myList is declared and what the intended logic is in pushChar.

How do you determine what kind of node you are dealing with in yaml-cpp?

I'm reading the tutorial code here: https://code.google.com/p/yaml-cpp/wiki/Tutorial
One example goes like this:
YAML::Node primes = YAML::Load("[2, 3, 5, 7, 11]");
for (YAML::const_iterator it=primes.begin();it!=primes.end();++it) {
std::cout << it->as<int>() << "\n";
}
And the next like this:
YAML::Node lineup = YAML::Load("{1B: Prince Fielder, 2B: Rickie Weeks, LF: Ryan Braun}");
for(YAML::const_iterator it=lineup.begin();it!=lineup.end();++it) {
std::cout << "Playing at " << it->first.as<std::string>() << " is " << it->second.as<std::string>() << "\n";
}
However, if you swap the YAML files between these two cases, you will get an error, as you are accessing a map iterator for a sequence or vice versa:
terminate called after throwing an instance of 'YAML::InvalidNode'
what(): yaml-cpp: error at line 0, column 0: invalid node; this may result from using a map iterator as a sequence iterator, or vice-versa
For an arbitrary YAML input, how can I determine whether I am dealing with a sequence or a map in the loop (ie whether I should be using ->first or not) without using a try/catch block?
I tried looking for the documentation, but I could not find it.
UPDATE:
This is what I am trying to do:
YAML::Node config = YAML::LoadFile(filename);
for (YAML::const_iterator it=config.begin();it!=config.end();++it) {
if (it->Type() == YAML::NodeType::Map) { // exception
std::cout << it->first.as<std::string>();
} else if (it->Type() == YAML::NodeType::Sequence) {
std::cout << it->as<std::string>();
}
}
But when I run the code I get the exception as above. It compiles fine.
I am using the yaml-cpp which comes with ubuntu 14.04 (0.5.1).
You can either
switch (node.Type()) {
case Null: // ...
case Scalar: // ...
case Sequence: // ...
case Map: // ...
case Undefined: // ...
}
or query explicitly, e.g.:
if (node.IsSequence()) {
// ...
}
(I added this bit to the Tutorial.)
Edit: In your specific example, you should check config.Type() before you iterate, not the type of any of the nodes during your iteration.

Techniques for testing and report multiple function call return errors

I'm looking at error testing and reporting techniques from function calls, especially when multiple functions are called. As an example of what I mean, for simplicity each function returns a bool:
success = false;
if (fnOne ())
{
if (fnTwo ())
{
if (fnThree ( ))
{
success = true;
}
else
{
cout << "fnThree failed" <<endl;
}
}
else
{
cout << "fnTwo failed" <<endl;
}
}
else
{
cout << "fnOne failed" <<endl;
}
I find with the above example (which I see everywhere) the code quickly becomes unreadable, especially when it calling code becomes multi-screen in height.
Currently my way of dealing with this in C++ (Including 'c' tag in case someone has a C technique which is smooth) I store a bool and a string in my object. The bool represents success/fail and the string represents a reason for the fail state. I call a function and if the function fails, the function internally sets the object into fail state and provides a string based reason. I'm still not 100% happy with this method... but its the best I have so far. Example of what it looks like:
void myobj::fnOne (void)
{
if (m_fluxCapacitorProngCount > 3)
{
setState (false, "myobj::fnOne - Flux capacitor has been breeding again");
}
}
void myobj::fnTwo (void)
{
if (m_answerToLifeUniverseAndEverything != 42)
{
setState (false, "myobj::fnTwo - Probability drive enabled?");
}
}
void myobj::setup (void)
{
// Ensure time travel is possible
if (valid())
{
fnOne ();
}
// Ensure the universe has not changed
if (valid())
{
fnTwo ();
}
// Error? show the reason
if (valid() == false)
{
cout << getStateReason () << end;
}
}
Where valid () returns true/false and getStateReason () returns the string provided in the function when the error occured.
I like that this grows without the need to nest the conditions, to me I find this more readable but I'm sure there are problems...
What is the best [cleanest] way to handle detecting and reporting multiple function call return conditions?
This code should be clearer than your first variant:
if (!fnOne ())
{
cout << "fnOne failed" <<endl;
return;
}
if (!fnTwo ())
{
cout << "fnTwo failed" <<endl;
return;
}
if (!fnThree ())
{
cout << "fnThree failed" <<endl;
return;
}
success = true;
In general, for C++ you can use exceptions for error handling.
If you really want one function to return a value that represents the success/failure of several other functions (and just that - not a generalized return value from each function, which would require some way of returning an array/tuple/vector of values), here's one approach:
int bigFunction()
{ int return_value = 0;
if (function1() != 0)
return_value |= (1 << 0);
if (function2() != 0)
return_value |= (1 << 1);
if (function3() != 0)
return_value |= (1 << 2);
// ....
return return_value;
}
The idea is to allocate one bit each in the return value to indicate success/failure of each sub-function. If your sub-functions have a small set of possible return values that you actually want to capture, you could use more than one bit per function - i.e. two bits would allow you four different values for that field.
On the other hand, something like this means you're probably either a) writing some pretty low-level code like a device driver or kernel or something or b) there is probably a better approach to solving the problem at hand.
Dealing with errors in your code (bugs) and errors arising out of user input is a huge topic on its own. The technique you employ depends on the complexity of your code and the expected life of the code. The error handling strategy you would employ for a homework project is less complex than the error handling strategy you would employ for a semester project, which will be less complex than the error handling strategy you would employ for an in-house project, which will be less complex than a project which will be widely distributed to clients.
Strategy 1: Write an error message and abort
The simplest error handling strategy, that you can employ in homework project, is write a message out to stdout and and then call abort().
void fun1(int in)
{
if (in < 0 )
{
printf("Can't work with a negative number.\n");
abort();
}
// Rest of the function.
}
Strategy 2: Set a global error code and return
The next level of error handling involves detecting a bad input and dealing with it without calling abort(). You could set a globally accessible error code to indicate the type of error. I would recommend using this approach for homework projects, semester projects, and projects that are exploratory in nature.
void fun2(int in)
{
if (in < 0 )
{
// Indicate that "fun2" came accross a NEGATIVE_INTEGER_ERROR.
setErrorCode(NEGATIVE_INTEGER_ERROR, "fun2");
return;
}
// Rest of the function.
}
void funUser(int in)
{
// Call fun2
fun2(in);
// If fun2 had any errors, deal with it.
if (checkErrorCode())
{
return;
}
// Rest of the function.
}
The next level of error handling involves detecting a bad input and dealing with it using other options. You could return an error code from the function. If you are using C++, you could throw an exception. Both these options are valid ways of dealing with large projects --- be they in-house or distributed for wider consumption. They are applicable to any project in which the user base is beyond the team of developers.
Strategy 3: Return an error code from the function
int fun3(int in)
{
if (in < 0 )
{
// Indicate that "fun3" came accross a NEGATIVE_INTEGER_ERROR.
return NEGATIVE_INTEGER_ERROR;
}
// Rest of the function.
}
void funUser(int in)
{
// Call fun3
int ecode = fun3(in);
// If fun3 had any errors, deal with it.
if (ecode)
{
return;
}
// Rest of the function.
}
Strategy 4: Throw an error code from the function (C++)
void fun4(int in)
{
if (in < 0 )
{
// Indicate that "fun4" came accross a NEGATIVE_INTEGER_ERROR.
throw NEGATIVE_INTEGER_ERROR;
}
// Rest of the function.
}
void funUser(int in)
{
// Call fun4. Be prepared to deal with the exception or let it be
// dealt with another function higher up in the call stack.
// It makes sense to catch the exception only if this function do
// something useful with it.
fun4(in);
// Rest of the function.
}
Hope this gives you enough background to adopt an appropriate error handling strategy for your project.

Assigning and Conditional Testing Simultaneously in C++

I have three functions that return integer error codes, e.g.
int my_function_1(const int my_int_param);
int my_function_2(const int my_int_param);
int my_function_3(const int my_int_param);
I want to assign and test for error at the same time for brevity. Will the following work and be portable?
int error=0;
...
if ( error ||
(error = my_function_1(val1) ||
error = my_function_2(val2) ||
error = my_function_3(val3)) ) {
std::cout << "AN ERROR OCCURRED!!!" << std::endl;
}
Thanks!
Why not throw an exception?
void my_function_1(const int my_int_param);
void my_function_2(const int my_int_param);
void my_function_3(const int my_int_param);
try {
my_function_1(...);
my_function_2(...);
my_function_3(...);
} catch(std::exception& e) {
std::cout << "An error occurred! It is " << e.what() << "\n";
}
I don't understand why you have the error && at the beginning of the function, but the rest should do what you want. Short circuit evaluation of the || operators is guaranteed by the standard. I would consider it bad style though.
Edit: Based on your comment, you would need to replace error && with error ||. I will also add that this is a good reason to use exceptions rather than error codes, it makes your code so much easier to read.
error is initialized to 0.So the && will always evaluates to false. So other parts of the if condition are never evaluated. So this code will not work. If you remove the && condition the code should work portably as the standard guarantees the order of the evaluation in this case.
Yes, after the minor change of && with || it will work. But it's just too confusing (using = in tests is confusing) with not much benefit.
You could go for exception line another poster suggested, or simply put your checked code inside function and do like below.
int checked(){
int error = 0;
error = my_function_1(val1); if (error) return error;
error = my_function_2(val1); if (error) return error;
error = my_function_3(val1); if (error) return error;
return error;
}
I believe any programmer will easily understand what is done here.