I am facing a situation where i need cppchecks to pass but it gets tricky sometimes. What do you generally do in such circumstances ?
For example.
#include<iostream>
using namespace std;
void fun1();
int fun2();
int main()
{
fun1();
}
void fun1()
{
int retVal;
if (-1 == (retVal = fun2()))
{
cout <<"Failure. fun2 returned a -1"<< endl;
}
}
int fun2()
{
return -1;
}
We usually see code such as the above. cppcheck for the above file would give an output as below -
cppcheck --suppress=redundantAssignment
--enable='warning,style,performance,portability' --inline-suppr --language='c++' retval_neverused.cpp Checking retval_neverused.cpp... [retval_neverused.cpp:13]: (style) Variable 'retVal' is assigned a
value that is never used.
I don't want to add some dummy line printing retVal just for the sake of cppcheck. Infact it can be a situation where I throw an exception and I don't want the exception to have something trivial as the value of retVal in it.
CppCheck is kinda right though. You don't need retVal at all. just check the return value of fun2 directly: if( -1 == fun2() )
As an aside, assigning variables inside conditional expressions is really bad practice. It makes it a lot harder to catch typos where you meant to type == but actually typed =.
You could rewrite as:
const int retval = fun2();
if (retval == -1)
This technique is, IMHO, easier to debug because you can see, with a debugger, the value returned from fun2 before the if statement is executed.
Debugging with the function call in the if expression is a little more complicated to see the return value from the function.
One common way is with something like this:
#define OK_UNUSED(x) (void)x
void fun1()
{
int retVal;
if (-1 == (retVal = fun2()))
{
OK_UNUSED (retVal);
cout <<"Failure. fun2 returned a -1"<< endl;
}
}
This indicates to humans that retVal is intentionally unused and makes CppCheck think it's used, suppressing the warning.
Note that this macro should not be used if evaluating its parameter has consequences. In that case, you need something fancier like:
#define OK_UNUSED(x) if(false && (x)) ; else (void) 0
Related
In some cases it happens for me to declare a variable without knowing its value first like:
int a;
if (c1) {
a = 1;
} else if (c2) {
a = 2;
} else if (c3) {
a = -3;
}
do_something_with(a);
Is it the standard professional practice to assign some clearly wrong value like -1000 anyway (making potential bugs more reproducible) or it is preferred not to add the code that does nothing useful as long as there are no bugs? From one side, looks reasonable to remove randomness, from the other side, magical and even "clearly wrong" numbers somehow do not look attractive.
In many cases it is possible to declare when the value is first known, or use a ternary operator, but here we would need it nested so also rather clumsy.
Declaring inside the block would move the variable out of the scope prematurely.
Or would this case justify the usage of std::optional<int> a and assert(a) later, making sure we have the value?
EDIT: The bugs I am talking about would occur if suddenly all 3 conditions are false that should "absolutely never happen".
As far as I know the most popular and safest way is using inline lambda call. Note that the if should be exhaustive (I added SOME_DEFAULT_VALUE as a placeholder). I suppose that if you don't know what to put in final else block you should consider a few options:
using optional and putting none in the else,
throwing exception that describes the problem,
putting assert if logically this situation should never happen
const int a = [&] {
if (c1) {
return 1;
} else if (c2) {
return 2;
} else if (c3) {
return -3;
} else {
return SOME_DEFAULT_VALUE;
}
}();
do_something_with(a);
In a situation when the initialization logic duplicates somewhere you can simply extract the lambda to a named function as other answers suggest
In my opinion, the safest option, if you dont want this other value (its just useless), then it may lead to really subtle bug which may be hard to find. Therefore I would throw an expectation when any of the conditions is not met:
int get_init_value(bool c1, bool c2, bool c3) {
if (c1) { return 1; }
else if (c2) { return 2; }
else if (c3) { return -3; }
throw std::logic_error("noone of conditions to define value was met");
}
That way we avoid getting some weird values that want actually match our code, but they would compile anyways ( debugging it may take a lot of time). I consider it way better than just assigning it some clearly wrong value.
Opinion based answer!
I know the example is a simplification of a real, more complex example, but IMHO it seems nowadays this kind of design issue emerge more often, and people sometimes kinda tend to over-complicate it.
Isn't it the whole purpose of a variable to hold some value? Thus isn't having a default value for this variable also a feasible thing?
So what exactly is wrong with:
int a = -1000; // or some other value meant to used for undefined
if (c1) {
a = 1;
} else if (c2) {
a = 2;
} else if (c3) {
a = -3;
}
do_something_with(a);
It is simple and readable... No lambdas, exceptions and other stuff making the code unnecessary complicated...
Or like:
int a;
if (c1) {
a = 1;
} else if (c2) {
a = 2;
} else if (c3) {
a = -3;
} else {
a = -1000; // default for unkown state
}
do_something_with(a);
You could introduce a constant const int undefined = -1000; and use the constant.
Or an enum if c1, c2, c3 are states in some sort (which it most likely is)...
You could rearrange the code to eliminate the variable if it is not needed elsewhere.
if (c1) {
do_something_with(1);
} else if (c2) {
do_something_with(2);
} else if (c3) {
do_something_with(-3);
}
I would introduce a default value. I'm usually using MAX value of the type for this.
Shortest you can do this with the ternary operator like this:
#include <climits>
int a = c1 ? 1 : c2 ? 2 : c3 ? -3 : INT_MAX;
do_something_with(a);
I understand your real code is much more complicated than the outline presented, but IMHO the main problem here is
should we do_something_with(a) at all if a is undefined,
rather than
what the initial value should be.
And the solution might be adding explicitly some status flag like a_is_defined to the actual parameter a instead of using magic constans.
int a = 0;
bool a_is_defined = false;
When you set them both according to c... conditions and pass them to do_something() you'll be able to make a clear distinction between a specific if(a_is_defined) {...} path and a default (error handling?) else {...}.
Or even provide separate routines to explicitly handle both paths one level earlier: if(a_is_defined) do_someting_with(a); else do_something_else();.
I know that something like this is possible, I just forgot how to do it properly.
if (true)
printf("something"), return;
return is not an expression, so it cannot be an operand of the comma operator.
Here is a (trivially) one-line version that works:
if (true) { printf("something"); return; }
(Note: one-line-ness is overrated. Write for readability, not brevity, and if they coincide, win-win. Granted, I myself should follow my advice more often...)
EDIT: You might be thinking of some variation of
if (true) return (void) printf("something"); // for void functions
if (true) return printf("something"), 0; // for an e.g. int function
which works, but is ugly and hacky, as it obscures what is being returned. I don't endorse their use.
If the return type is std::list<int> then you need to return std::list<int>. You can't simply return nothing, which is what your code is trying to do.
A quick fix will be:
if (true)
{
printf("something");
return {};
}
Using brace initialization this will return an empty std::list<int>. Then whatever calls this function will have to check for an empty list.
In C++17 we have std::optional that allows us to to return an optional value: it can be value or no value.
So you could change your function signature to return std::optional<std::list<int>> like this:
std::optional<std::list<int>> getList()
{
if (true)
return {};
...
}
Here we are returning a nullopt_t for the true case. Then the code calling this function will have to check a value is returned:
auto l = getList();
if (l.has_value()) //or simply if (l)
{
//Do something with l.value() //or simply *l
}
Her's a little example: https://godbolt.org/z/SXbZSq
I have a function which returns zero on success, or the line number where an error was detected:
int func() {
// stuff
if (something is wrong) {
return __LINE__;
}
// more stuff
if (something else is wrong) {
return __LINE__;
}
// all good
return 0;
}
Real callers only check whether the return value is zero or not, often like this:
int ret = func();
if (ret != 0) {
return ret;
}
However, during tests I would like to check the actual return value, to verify that a certain fail condition was triggered:
int ret = func();
EXPECT_EQ(42, ret);
This poses a problem, because when the source file of func() is edited, the lines of the return statements, and hence the values returned, also change. I would like the line number values to be available to the callers of func().
It is possible to "export" line numbers like this:
// header
extern const int line_number;
// source
const int line_number = __LINE__;
Unfortunately, this only works for line numbers outside a function. I would like something like this:
if (something is wrong) {
const int line_number = __LINE__; return __LINE__;
// or some other const thing
}
that can be read from another translation unit (file).
I tried static const int line = __LINE__, but that has two flaws:
it's not the definition of line_number declared in the header.
it may not be set until execution passes over it.
Here an example how I would solve this easily:
struct FuncErrorCodes {
enum Type {
OK = 0,
SOMETHING_IS_WRONG,
SOMETHING_ELSE_IS_WRONG,
...
};
};
typedef FuncErrorCodes::Type FuncErrorCode;
FuncErrorCode func() {
// stuff
if (something is wrong) {
return FuncErrorCodes::SOMETHING_IS_WRONG;
}
// more stuff
if (something else is wrong) {
return FuncErrorCodes::SOMETHING_ELSE_IS_WRONG;
}
...
// all good
return FuncErrorCodes::OK;
}
I don't see any reason why I would want to use __LINE__ for error codes.
In the usual case the return code can still be tested against 0 (or better yet FuncErrorCodes::OK) and I'd have no problem testing for the particular error reasons, like for example:
FuncErrorCode rc = func();
EXPECT_EQ(FuncErrorCodes::SOMETHING_IS_WRONG, ret);
EDIT: Note that even if you managed to export the "last line set to the error code" it would not help you in any way, because that would be the exact value the function is returning (so you already know it). For it to actually work, you would need separate variable for each possible error line, which will then contain the particular line number (so that it can be checked against the function return code to see if the particular error happened).
I.e. you would need something like:
extern int something_wrong_line_number;
extern int something_else_wrong_line_number;
if (something is wrong) {
something_wrong_line_number = __LINE__; return __LINE__;
}
if (something else is wrong) {
something_else_wrong_line_number = __LINE__; return __LINE__;
}
// etc. - but it will of course still not work entirely well because the __LINE__ is only assigned if the error actually happens
And that is then no different to providing just the simple error codes for each particular error situation as I suggest (and it is much more complicated).
Is there a better way for this "idiom"?
if(State s = loadSomething()) { } else return s;
In other words, I want to do something, which may return an error (with a message) or a success state, and if there was an error I want to return it. This can become very repetitive, so I want to shorten it. For example
if(State s = loadFoobar(&loadPointer, &results)) { } else return s;
if(State s = loadBaz(&loadPointer, &results)) { } else return s;
if(State s = loadBuz(&loadPointer, &results)) { } else return s;
This must not use exceptions which I would favor otherwise (unsuitable for this build). I could write up a little class BooleanNegator<State> that stores the value, and negates its boolean evaluation. But I want to avoid doing this ad-hoc, and prefer a boost/standard solution.
You could do:
for (State s = loadSomething(); !s; ) return s;
but I am not sure if it is more elegant, and it is definitely less readable...
I assume the context is something like
State SomeFunction()
{
if(State s = loadSomething()) { } else return s;
return do_something_else();
}
without throwing exceptions where do_something_else() does something of relevance to SomeFunction() and returns a State. Either way, the result of continuing within the function needs to result in a State being returned, as falling off the end will cause the caller to exhibit undefined behaviour.
In that case, I would simply restructure the function to
State SomeFunction()
{
if (State s = loadSomething())
return do_something_else();
else
return s;
}
Implicit assumptions are that State has some operator (e.g. operator bool()) that can be tested, that copying a State is possible (implied by the existence of a loadSomething() that returns one) and relatively inexpensive, and that two instances of State can exist at one time.
Aside from some smart/hacky uses of different keywords to get the same behavior, or adding more-or-less complex extra templates or macros to get unless() keyword or to somehow manage to inject ! operator, I'd stick to just the basic things.
This is one of the places I'd (probably) inject extra "unnecessary" brackets:
void someFunction()
{
// some other code
{ State s = loadSomething(); if(!s) return s; }
// some other code
}
However, in this exact case, I'd expand it to emphasise the return keyword, which can be easily overlooked when it's squashed to a one-liner. So, unless the one-liner is repeated many times and unless it's clear&obvious that there's a return inside, I'd probably write:
void someFunction()
{
// some other code
{
State s = loadSomething();
if(!s)
return s;
}
// some other code
}
It might look like elevating the scope of the s, but actually it is equivalent to declaring State s in if(). All thanks to the extra brackets which explicitly limit the visibility of local s.
However, some people just "hate" seeing { .. } not coupled with a keyword/class/function/etc, or even consider it to be unreadable due to "suggesting that a if/while/etc keyword was accidentally deleted".
One more idea came to me after you added the repetitive example. You could have tried a trick known from scripting languages where && and || may return a non-bool values:
State s = loadFoobar(&loadPointer, &results);
s = s || loadBaz(&loadPointer, &results);
s = s || loadBuz(&loadPointer, &results);
if(!s) return s;
however there's a problem: in contrast to script languages, in C++ such overloads of && and || lose their short-circuit semantics which makes this attempt pointless.
However, as dyp pointed out the obvious thing, once the s scope is elevated, now simple if can be introduced back. Its visibility can be limited back again with extra {}:
{
State s;
if(!(s = loadFoobar(&loadPointer, &results))) return s;
if(!(s = loadBaz(&loadPointer, &results))) return s;
if(!(s = loadBuz(&loadPointer, &results))) return s;
}
Assume I have the following function:
// Precondition: foo is '0' or 'MAGIC_NUMBER_4711'
// Returns: -1 if foo is '0'
// 1 if foo is 'MAGIC_NUMBER_4711'
int transmogrify(int foo) {
if (foo == 0) {
return -1;
} else if (foo == MAGIC_NUMBER_4711) {
return 1;
}
}
The compiler complains "missing return statement", but I know that foo never has different values than 0 or MAGIC_NUMBER_4711, or else my function shall have no defined semantics.
What are preferable solutions to this?
Is this really an issue, i.e. what does the standard say?
Sometimes, your compiler is not able to deduce that your function actually has no missing return. In such cases, several solutions exist:
Assume the following simplified code (though modern compilers will see that there is no path leak, just exemplary):
if (foo == 0) {
return bar;
} else {
return frob;
}
Restructure your code
if (foo == 0) {
return bar;
}
return frob;
This works good if you can interpret the if-statement as a kind of firewall or precondition.
abort()
if (foo == 0) {
return bar;
} else {
return frob;
}
abort(); return -1; // unreachable
Return something else accordingly. The comment tells fellow programmers and yourself why this is there.
throw
#include <stdexcept>
if (foo == 0) {
return bar;
} else {
return frob;
}
throw std::runtime_error ("impossible");
Disadvantages of Single Function Exit Point
flow of control control
Some fall back to one-return-per-function a.k.a. single-function-exit-point as a workaround. This might be seen as obsolete in C++ because you almost never know where the function will really exit:
void foo(int&);
int bar () {
int ret = -1;
foo (ret);
return ret;
}
Looks nice and looks like SFEP, but reverse engineering the 3rd party proprietary libfoo reveals:
void foo (int &) {
if (rand()%2) throw ":P";
}
This argument does not hold true if bar() is nothrow and so can only call nothrow functions.
complexity
Every mutable variable increases the complexity of your code and puts a higher burden on the cerebral capacity on your code's maintainer. It means more code and more state to test and verify, in turn means that you suck off more state from the maintainers brain, in turn means less maintainer's brain capacity left for the important stuff.
missing default constructor
Some classes have no default construction and you would have to write really bogus code, if possible at all:
File mogrify() {
File f ("/dev/random"); // need bogus init because it requires readable stream
...
}
That's quite a hack just to get it declared.
In C89 and in C99, the return statement is never required. Even if it is a function that has a return different than void.
C99 only says:
(C99, 6.9.1p12 "If the } that terminates a function is reached, and the value of the function call is used by the caller, the behavior is undefined."
In C++11, the Standard says:
(C++11, 6.6.3p2) "Flowing off the end of a function is equivalent to a return with no value; this results in undefined behavior in a value-returning function"
Just because you can tell that the input will only have one of two values doesn't mean the compiler can, so it's expected that it will generate such a warning.
You have a couple options for helping the compiler figure this out.
You could use an enumerated type for which the two values are the only valid enumerated values. Then the compiler can tell immediately that one of the two branches has to execute and there's no missing return.
You could abort at the end of the function.
You could throw an appropriate exception at the end of the function.
Note that the latter two options are better than silencing the warning because it predictably shows you when the pre-conditions are violated rather than allowing undefined behavior. Since the function takes an int and not a class or enumerated type, it's only a matter of time before someone calls it with a value other than the two allowed values and you want to catch those as early in the development cycle as possible rather than pushing them off as undefined behavior because it violated the function's requirements.
Actually the compiler is doing exactly what it should.
int transmogrify(int foo) {
if (foo == 0) {
return -1;
} else if (foo == MAGIC_NUMBER_4711) {
return 1;
}
// you know you shouldn't get here, but the compiler has
// NO WAY of knowing that. In addition, you are putting
// great potential for the caller to create a nice bug.
// Why don't you catch the error using an ELSE clause?
else {
error( "transmorgify had invalid value %d", foo ) ;
return 0 ;
}
}