C++ Quiz
q.viva64.com
q.viva64.com
One of the first things a programming guru told me was basically: whenever you are ready to hit Crl-C/Ctrl-V (or Ctrl-D or whatever 'duplicate' is in your editor) you shall ask yourself if you are not going to violate the all-important DRY rule. Ignorant and stubborn as I was at the time being I was like 'pfffft what can be wrong with some copy-pasting'. As I learned through the years and is shown by this quiz: a whole lot obviously. It can not be stressed enough how important and widely applicable yet so simple DRY principle is. So as a call-out to all programmers who haven't learnt the habit yet: please think twice or more before even considering copy-pasting.
It's not an excuse, but languages definitely shape how you think, and C++ definitely encourages long functions and copy pasta.
Once you are a C++ programmer for a while, you start to discern "standard" patterns for this sort of thing and tend to automatically use them. (The patterns might depend on the C++ version and to an extent the code base in question; but it is common to have such helper function take a const ref as input, return non-primitive return values via a out-parameter etc).
So while C++ might "encourage long functions", I think that may be the case only for newbies to the language. Once you have a some experience working with it, you no longer need to put that much thought in to every little decision.
I was able to spot 13 of these errors -- although the page only counted that as 10 as it's very picky of which token constitutes the error.
PVS Studio (and CppCat) are great tools. I can't unfortunately use them as I don't write stuff for Windows.
In addition to them, I also use Coverity (they offer free licenses for open source projects) and Coccinelle (although it's a tool to refactor/create semantic patches, can be also used to find defects if you know what you're looking for -- useful if you fix one bug and you're wondering if there are more like it lurking).
Having different opinions about your codebase is often good as the approach in finding defects is usually different between them. For instance, stuff by the PVS people seem pretty good to find copy/paste mistakes, which I've rarely found with other tools.
Static code analysis is fantastic for a language like this (if you can afford it; not sure what the pricing on this product is -- can't say I've ever seen a cheap static code analyzer though :-) )
I did well, because I was actually looking for bugs; and I didn't write the code, so had no preconceived notions of what it was supposed to do.
When you have 10s or 100s of thousands of lines of code in your project, however, you aren't going to know where to look for a bug (because they could be anywhere or everywhere); and one can often be blinded by knowing how it is supposed to read, not how it actually reads.
int SSL_shutdown(SSL *s)
{
if (s->handshake_func == 0)
{
SSLerr(SSL_F_SSL_SHUTDOWN, SSL_R_UNINITIALIZED);
return -1;
}
if ((s != NULL) && !SSL_in_init(s))
return(s->method->ssl_shutdown(s));
else
return(1);
}
....
}
so of course the first thing I noticed was the mismatched braces after the 'else'. The 'intended' error was elsewhere (and I agree with it) but to say that the brace isn't an error is a bit much given the sorts of problems that PVS is normally finding.It's a good practice to always use braces with if / else even if it's just one line in them.
That lone } which seemingly belongs to if in this case would be closing the function.
There are also some ambiguities. At least two questions I encountered contained more than one bug, or at least one explicit bug and one "occasional" bug due to a lack of testing in the code (say, for division by zero).
Also, it'd be a a good idea to put a disclaimer for the quiz taker to assume types, variables and other tokens are declared properly. It's easy to make the deduction after getting the first question which you get incorrect because you chose the "wrong" bug.
[0]Because of course, when you know there's a bug, it's already easier to find...
On question 2 it gave me 60 seconds to visually deconstruct a statement, which is pretty unfair.
I gave up after that. I guess this thing exists to "show" you that you can't spot any errors and that you should just buy their tool?
I was mislead by
int t1 = something.getArg(1);
int t2 = something.getArg(); //I clicked here
...
something else with the error they had in mindLet's simplify the code to make the error more obvious:
if (a & Min_Max) { Min[0] Min[1] }
else if (a & Max_Min) { Max[0] Min[1] }
else if (a & Max_Max) { Max[0] Max[1] }
else if (a & Min_Max) { Min[0] Max[1] }
It should be evident now that every line except the first one contains the correlation between names of constants and names of arrays. So, in the first expression the 'sC0Min1Min' should have been used instead.I promised myself I'd walk out on any quiz in the future. I haven't had to hold myself to that so far.
So it had to be found again: https://news.ycombinator.com/item?id=8335217
CV_IMPL IplImage * icvCreateIsometricImage(....)
{
....
if (!dst || dst->depth != desired_depth ||
dst->nChannels != desired_num_channels ||
dst_size.width != src_size.width ||
dst_size.height != dst_size.height)
....
}
The website said the error was 'height was compared with itself', fair enough ... but there is a much much bigger crime here.I clicked on the (!dst ||) as the code checks for a null pointer and then follows that with a dereference of that pointer which will get executed because of the || operator.
If the pointer is null the code will still crash.
The website said I was wrong .... I didn't bother with any more questions after that.
I'm chiming in not to pile on, but to point out this is a canonical code pattern in C and C++. Check the pointer, then deference it, all in the same if expression.
if (ptr && ptr->foo...
or if (!ptr || !ptr->foo...