-
Cutest bug you have ever seen?
Hey guys, this is my first post here. What better way to introduce myself than with an interesting programming story?
I'm a student currently participating as a programmer for FIRST Robotics Competition Team 339. In my three years on the team I have learned almost every nuance of C++ imaginable, from boolean operators to template metaprogramming.
One of the my most interesting encounters with obscure C++ syntax, however, occurred very recently, at a competition a few weeks ago. Someone from another team who is somewhat new to C++ showed me code similar to the following and asked why it compiled but gave him bogus results:
Code:
# include <iostream>
using namespace std;
int main()
{
float f[2][2] = {1.0, 2.0, 3.0, 4.0};
int i = (int)f[1, 1];
cout << i << endl;
}
I just had to chuckle when I saw this one. I'm not sure what's worse: the fact that someone had written this code or the fact that I took one look at it and immediately knew what the problem was. I now refer to this example as the "cutest bug of all time".
So, I thought I'd ask others on this site: what do you think is the "cutest" C++ bug you have ever seen? Where have you seen that perfect combination of simplicity and obscurity that means you just have to laugh when you discover the solution?
Oh, and as for the answer to my example: I'll leave it unsolved just to see what others think. What would the output be? Why does it compile? What safer coding practice would have prevented this?
I'm hoping this will turn out to be an interesting topic. Enjoy!
-
Re: Cutest bug you have ever seen?
No, this is not a interesting story.
The integer after decimal is just ignored by integer.
Please correct me if wrong.
-
Re: Cutest bug you have ever seen?
Quote:
Originally Posted by Peter_APIIT
No, this is not a interesting story.
The integer after decimal is just ignored by integer.
Please correct me if wrong.
Try it and see. :D
-
Re: Cutest bug you have ever seen?
Integers can't store decimal numbers, so the stuff after the decimal point is just truncated.
If you change i to a floating point number, then this truncation won't happen.
-
Re: Cutest bug you have ever seen?
Oh, and he is actually converting a float* to an integer...
-
Re: Cutest bug you have ever seen?
1,1 evaluates to 1 in C/C++. Thus, f[1,1] is equal to f[1].
The print statement is equal to
Code:
cout << (int)f[1] << endl;
A conversion from pointer to int.
In Fortran, you access array elements as f(1,1). In C/C++, you need to use f[1][1].
-
Re: Cutest bug you have ever seen?
Unless you have overloaded the comma operator. :D :D :D :eek:
-
Re: Cutest bug you have ever seen?
Yes, that's it. The array dereferencing syntax is wrong - he should have typed [1][1] instead of [1, 1]. The funny thing is, this compiled without problem thanks to the explicit (int) cast. A static_cast<int>() would have been a better choice.
Why do I call it the cutest bug of all time? Because this code compiled through a bizarre combination of circumstances:
1. The guy writing it forgot how to dereference a two-dimensional array - that should normally be a syntax error.
2. The guy's best guess turned out to be something very different but completely legal in C++ (the comma operator) - okay, but its still a compile error due to the illegal pointer conversion.
3. The guy was already casting to int, which incidentally erased all traces of the illegal conversion.
After looking at the code, this was my explanation of the problem: "you see this comma in the square brackets? In this context, it is known as the comma operator, and it was included in the language to annoy you when you accidentally used it."
Does anyone else have an example of a similar "cute" bug they have seen?
(BTW, I find it funny that two members offered me a nice explanation of floating point truncation before noticing the real problem. :D)
-
Re: Cutest bug you have ever seen?
Quote:
Originally Posted by (V|G)CC4ME
.... In this context, it is known as the comma operator, and it was included in the language to annoy you when you accidentally used it....
Not at all, the comma operator is critical to certain operations.
And overloading it is one of the most efficiant ways to perform complex initializations......
-
Re: Cutest bug you have ever seen?
Why isn't this code working? :cool:
Code:
#define x 9;
int main()
{
int i = 0;
while (i++ < x)
cout << i << endl;
return 0;
}
-
Re: Cutest bug you have ever seen?
Extra semicolon!
That one took a moment.
-
Re: Cutest bug you have ever seen?
You mean "not compiling"? ";" after the 9 in #define.
-
Re: Cutest bug you have ever seen?
For my own part, just recently I spotted a for loop where I was trying to iterate over two lists (of different lengths) at once. Comma operator in the initializer clause. Comma operator in the increment cause. And because everything *had* to be aligned nicely to look uncluttered......yup, you guessed it, I had a comma operator in the termination condition too....
-
Re: Cutest bug you have ever seen?
Quote:
Originally Posted by Lindley
For my own part, just recently I spotted a for loop where I was trying to iterate over two lists (of different lengths) at once. Comma operator in the initializer clause. Comma operator in the increment cause. And because everything *had* to be aligned nicely to look uncluttered......yup, you guessed it, I had a comma operator in the termination condition too....
LOL, that's a good one. Would have been even better if those termination conditions had side effects.
-
Re: Cutest bug you have ever seen?
Something which happened to me when I was learning C++:
Code:
string s = getStringFromUser();
//iterate through string backwards
for(size_t pos = s.length() - 1; pos >= 0; --pos) {
cout << s[pos];
}
Took me hours to find the error.
And another one was when I mixed up i and j counter variables in nested for loops. Not funny.
One more it took me LONG time to find the error:
Code:
#include <iostream>
#include <string>
#include <vector>
#include <numeric>
#include <algorithm>
using namespace std;
int main()
{
vector<unsigned long long> vec;
vec.push_back(123456789012);
vec.push_back(987654321098);
unsigned long long result = accumulate(vec.begin(), vec.end(), 0);
cout << result;
}
I was getting incorrect results although it was guaranted there should be no overflow for unsigned long long type. Still, result was incorrect. Find an error and get a rep point from me :) (And no, you won't get it, TheCPUWizard. Let beginners have some fun :) )
Cheers
-
Re: Cutest bug you have ever seen?
Quote:
Originally Posted by Hobson
I was getting incorrect results although it was guaranted there should be no overflow for unsigned long long type. Still, result was incorrect. Find an error and get a rep point from me :)
I know! :D
this is pretty simple to me, but I am not a pro ;).
Code:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "Testing";
//iterate through string backwards
for(size_t pos = s.length() - 1; ; --pos) {
cout << s[pos] << endl;;
if(pos == 0) break;
}
}
Code:
#include <iostream>
#include <string>
#include <vector>
#include <numeric>
#include <algorithm>
using namespace std;
int main()
{
vector<unsigned long long> vec;
vec.push_back(123456789012LL);
vec.push_back(987654321098LL);
unsigned long long result = accumulate(vec.begin(), vec.end(), 0LL);
cout << result;
}
Do you want an explanation too? :D
-
Re: Cutest bug you have ever seen?
Good job! And no need for explanation, I got it by myself, however, when you are learning, it may take you some time :)
-
Re: Cutest bug you have ever seen?
I guess the accumulate issue was some time ago Hobson? This is captured by the compiler today.
-
Re: Cutest bug you have ever seen?
well the compiler gives a warning now
-
Re: Cutest bug you have ever seen?
I got stumped on this one for a while when I first learnt C. :rolleyes:
Code:
// Oops, infinite loop.
unsigned char c;
for (c = 0; c < 256; c++)
{
/// Do stuff.
}
-
Re: Cutest bug you have ever seen?
I don't think its an interesting story.
-
Re: Cutest bug you have ever seen?
Quote:
Originally Posted by (V|G)CC4ME
Code:
# include <iostream>
using namespace std;
int main()
{
float f[2][2] = {1.0, 2.0, 3.0, 4.0};
int i = (int)f[1, 1];
cout << i << endl;
}
Quote:
Originally Posted by (V|G)CC4ME
Oh, and as for the answer to my example: I'll leave it unsolved just to see what others think. What would the output be? Why does it compile?
Without reading other replies ...
1,1 evaluates to 1
f[1] evaluates to the address of the second row, i.e. &f[1][0]
That address is then cast to an int.
Quote:
Originally Posted by (V|G)CC4ME
What safer coding practice would have prevented this?
Use static_cast<int> instead of (int).
-
Re: Cutest bug you have ever seen?
One of the cutest bug I've seen was something like
Code:
// check if a is either 3 or 5
if (a == 3 | 5) {
And some of the cutest code (not a bug, works perfectly) I've seen was this (ok, it's JAVA, not C++):
Code:
for(int i=2;i<8;i++){
if(slotNumber.longValue() == i){
slotName = "Slot "+ (i-2);
}
}
Both pieces were written by "IT-professionals", not students.
-
Re: Cutest bug you have ever seen?
I must say I'm impressed guys. I've made so many bug's in my life I can't pick a favourite... :o
-
Re: Cutest bug you have ever seen?
For some reason, I like this one (access violation):
Code:
#include <iostream>
using namespace std;
char* numbers[10] = {
"One",
"Two",
"Three",
"Four",
"Five"
"Six",
"Seven",
"Eight",
"Nine",
"Ten"
};
int main()
{
for (int i = 0; i < 10; ++i)
{
std::cout << numbers[i] << " ";
}
return 0;
}
-
Re: Cutest bug you have ever seen?
Quote:
Originally Posted by Zachm
For some reason, I like this one (access violation):
Admittedly, I am not very familiar with the use of such global variables, but it seems to me that the problems with that example is not an access violation, but a missing semi-colon and that numbers should be an array of const char*.
EDIT:
Ah, the most obvious mistake is now corrected.
-
Re: Cutest bug you have ever seen?
Edited my last post.
Didn't try to compile it, but the semi-colon is not the problem I intended to demonstrate.
Disregard the fact that the array is global as well - this was just for demonstration purposes,
and look closer !
-
Re: Cutest bug you have ever seen?
hmm... after seeing your correction, I thought that perhaps I miscounted, but you have ten string literals in the array, and the array is of 10 char*, so where's the out of bounds access?
-
Re: Cutest bug you have ever seen?
Zachm, your code snippet just killed me. Awesome. I was staring at it trying to find a bug for like 15 minutes, until decided to run it and see. Great example :D
-
Re: Cutest bug you have ever seen?
Quote:
Zachm, your code snippet just killed me. Awesome. I was staring at it trying to find a bug for like 15 minutes, until decided to run it and see.
I ran it and did not get a seg fault... but I guess I was unlucky.
Yeah, I see the error now, but frankly, it was obscured by other mistakes :p
-
Re: Cutest bug you have ever seen?
Yes, that's a not so easy to spot thing. Hard enough to allow for trailing , these days. :)
-
Re: Cutest bug you have ever seen?
If you had only knew how many hours I spent looking for this problem :) - I wasn't so lucky as to get an access violation.
-
Re: Cutest bug you have ever seen?
That's a classic example of false assumptions (the assumption being that the code where the error is would be not contain an error).
I think the brain initially skips that part of the code because it just sees what it was expecting to see.
-
Re: Cutest bug you have ever seen?
Quote:
Originally Posted by Zaccheus
That's a classic example of false assumptions (that the code with the error would be ok).
Interestingly, if it were an array of std::string instead, it would really be "okay" in that an access violation would never happen, but the last element would mysteriously be an empty string.
-
Re: Cutest bug you have ever seen?
-
Re: Cutest bug you have ever seen?
Quote:
Originally Posted by laserlight
Interestingly, if it were an array of std::string instead, it would really be "okay" in that an access violation would never happen, but the last element would mysteriously be an empty string.
I didn't mean ok in the sense of "the bug not being a problem" but in the sense that I assumed the array was correctly defined.
-
Re: Cutest bug you have ever seen?
Quote:
#define x 9;
int main()
{
int i = 0;
while (i++ < x)
cout << i << endl;
return 0;
}
Preprocessor cannot checked by compiler. I guess why compiler flag an error.
-
Re: Cutest bug you have ever seen?
Quote:
Originally Posted by Hobson
One more it took me LONG time to find the error:
Code:
#include <iostream>
#include <string>
#include <vector>
#include <numeric>
#include <algorithm>
using namespace std;
int main()
{
vector<unsigned long long> vec;
vec.push_back(123456789012);
vec.push_back(987654321098);
unsigned long long result = accumulate(vec.begin(), vec.end(), 0);
cout << result;
}
I was getting incorrect results although it was guaranted there should be no overflow for
unsigned long long type. Still, result was incorrect. Find an error and get a rep point from me :) (And no, you won't get it, TheCPUWizard. Let beginners have some fun :) )
Cheers
You're bringing back memories! I (a student) along with a team mentor (a senior programmer at Computer Sciences Corporation (CSC)) once spent several hours debugging a missing "L" on the end of a # define. This was on a 16-bit embedded system, where "unsigned int" rolled over after 65535. No debugger was available - we had only printf() to work with. It wasn't fun.
-
Re: Cutest bug you have ever seen?
Quote:
Originally Posted by (V|G)CC4ME
You're bringing back memories! <snip> This was on a 16-bit embedded system <snip> No debugger was available - we had only printf() to work with. It wasn't fun.
I do not know of a single (commercial) 16 bit processor for which there is not a complete ICE solution with full debuffing capabilities available.
Granted, you may not have had access to one,but......
ps: I have been doing embedded systems development since the mid-1970's.
-
Re: Cutest bug you have ever seen?
Quote:
Originally Posted by TheCPUWizard
I do not know of a single (commercial) 16 bit processor for which there is not a complete ICE solution with full debuffing capabilities available.
Granted, you may not have had access to one,but......
ps: I have been doing embedded systems development since the mid-1970's.
Remember that I'm just talking about hobby/educational stuff. We were actually using this thing:
http://www.ifirobotics.com/rc.shtml
It uses the (8-bit, actually) PIC18F8722, but this proprietary implementation does not allow access to the debugging interface.
-
Re: Cutest bug you have ever seen?
Quote:
Originally Posted by (V|G)CC4ME
Remember that I'm just talking about hobby/educational stuff. We were actually using this thing:
http://www.ifirobotics.com/rc.shtml
It uses the (8-bit, actually) PIC18F8722, but this proprietary implementation does not allow access to the debugging interface.
I used that!!!!!
While somewhat limited the DDT (available from the vendor) is quite useful.
Also the PCM18XS2 will work as a full in-curcuit debugger allowing full capabilities.
-
Re: Cutest bug you have ever seen?
Quote:
Originally Posted by TheCPUWizard
I used that!!!!!
While somewhat limited the DDT (available from the vendor) is quite useful.
Also the PCM18XS2 will work as a full in-curcuit debugger allowing full capabilities.
Ugh. We took one look at the DDT (with its five whole pages of documentation) and decided it wasn't worthwhile.
We did eventually get the MPLAB SIM working, which was very helpful thereafter.
None of it matters anymore, however. Next year, we get to play with the National Instruments cRIO running under WindRiver vxWorks.
Anyway, to maybe get back on topic, here's another story. This one isn't a cute bug but rather a cute programming technique in general.
About five years ago, I decided to teach myself how to program by writing a scientific calculator in VB.NET. The problem is, I didn't know how to program. A few key points:
-I didn't know how to make an array, much less a stack, so I just created twelve global variables and push() and pop() subroutines, which looked like this:
Code:
stack1 = stack2
stack2 = stack3
stack3 = stack4
...
-I didn't know how to make a function that returned a value, so I just used a global variable called "answer".
-I didn't know how to parse a string, so I just selected (i.e. highlighted) the first letter in the input text box and called the selected letter the "pointer". To advance the "pointer", I would call up the System.Keyboard object and press the right arrow key! I guess I trusted my user to leave the window in focus during the parsing.
Amazingly, the program actually worked. I will never figure out how, but I somehow parsed an input string, converted it from infix to postfix, parsed the postfix expression, and calculated the result without knowing about arrays or return values.
Then, I took a real programming class and thought "you mean you can do that?!" at the start of every chapter.
Man, I wish I still had the source code for that thing. If I ever find it, I'm sure it will be a good laugh looking through and seeing what other clever things I did.
-
Re: Cutest bug you have ever seen?
For stories like this, read www.worsethanfailure.com . This site is dedicated for various WTFy stories related to IT. Gives great fun, and is really addictive. For you, CodeSOD series would be most interesting, I think, but check other series also, as well as comments to each entry! :wave:
-
Re: Cutest bug you have ever seen?
What wrong with the vector program ?
-
Re: Cutest bug you have ever seen?
Quote:
What wrong with the vector program ?
Two things actually but I have to admit that they weren't apparent at first. The fixed code should be:
Code:
#include <iostream>
#include <string>
#include <vector>
#include <numeric>
#include <algorithm>
using namespace std;
int main()
{
vector<unsigned long long> vec;
vec.push_back(123456789012ULL);
vec.push_back(987654321098ULL);
unsigned long long result = accumulate<std::vector<unsigned long long>::iterator, unsigned long long>(vec.begin(), vec.end(), 0ULL);
cout << result;
}
The funny thing is that gcc warns you about not tacking on "ULL" at the end of the constants while Microsoft's Compiler warns about not using the right template parameters for std::accumulate (well not in a straight-forward manner of course). Unfortunately, neither of those compilers will warn you about both the errors. :)
My story:
I was getting more and more frustrated as to why my physics code wasn't working. I calculated it on paper 3 to 4 times over again and it was supposed to work theoretically. I checked my implementation logic at least 10 times and reimplemented at least 3 variants of it. Finally I spotted the problem and fixed it. It resulted due to a trivial copy-paste error. Combined with the rest of the lengthy and messy code, it just escaped my sight till when I finally tracked down the error to be within a certain range of the code.
I was doing something like this: 1.0f / (a.OneOverMass(), b.OneOverMass());
Where, in fact, I was supposed to do this: 1.0f / (a.OneOverMass() + b.OneOverMass());
The difference was just that an addition got changed to a comma, but it made a huge difference!
Instead of getting the sum of the inverse masses of a and b, I was just getting the inverse mass of b.
This would result in a bigger impulse being applied than necessary, and create instability in the system.
-
Re: Cutest bug you have ever seen?
Quote:
Originally Posted by angelorohit
I was doing something like this: 1.0f / (a.OneOverMass(), b.OneOverMass());
Where, in fact, I was supposed to do this: 1.0f / (a.OneOverMass() + b.OneOverMass());
The difference was just that an addition got changed to a comma, but it made a huge difference!
Instead of getting the sum of the inverse masses of a and b, I was just getting the inverse mass of b.
This would result in a bigger impulse being applied than necessary, and create instability in the system.
Yet another shining example of where a TDD (test driven development) approach would have saved so much heartache.
If this equiation was a method (or function) and had a set of testcases, the problem would have been found before it was ever used as part of a larger equation.
-
Re: Cutest bug you have ever seen?
Cutest bug? Maybe not cute, but one of the most frustrating:
Code:
struct foo
{
int x;
int y;
int z;
char name[100];
};
Then in the code, to set these structs to 0, the codebase had this in various places:
Code:
foo f;
memset( &f, 0, sizeof(foo) );
This was working for many months. Along comes a programmer who decided to use std::string instead of char arrays for the name:
Code:
struct foo
{
int x;
int y;
int z;
std::string name;
};
Now, this code still worked for Visual C++ 6.0. When it was ported to C++ Builder, the code started to crash in random places. It took me a week to figure out what was going wrong.
Hopefully I don't need to explain the problem. If anyone reading this doesn't know what's wrong, then it's time to crack open the C++ books and learn about POD and non-POD types.
Regards,
Paul McKenzie
-
Re: Cutest bug you have ever seen?
Yes, I've come across that one. It created an intermittent bug in a totally unconnected area of the code. It took a lot of CrtCheckMemory() calls spread around the code before I tracked it down. I then made a Voodoo effigy of the coder responsible and got out the pins...
-
Re: Cutest bug you have ever seen?
Quote:
Originally Posted by Paul McKenzie
Now, this code still worked for Visual C++ 6.0. When it was ported to C++ Builder, the code started to crash in random places. It took me a week to figure out what was going wrong.
Hopefully I don't need to explain the problem. If anyone reading this doesn't know what's wrong, then it's time to crack open the C++ books and learn about POD and non-POD types.
Regards,
Paul McKenzie
(...Paul, of course you know this...)
A perfect example of why NOT to use VC++ 6.0. It (and earlier versions) wer non-compliant in so many ways.
This is one of the reasons many of use cringe when we read a post "I am using VC++ 6.0....".
I just completed a project where I was verifying a set of tests for a major provider. Many of their questions/answers (before I corrected them) where based on the improper behaviour of VC++ 6.0 :sick:
-
Re: Cutest bug you have ever seen?
Quote:
Originally Posted by TheCPUWizard
(...Paul, of course you know this...)
A perfect example of why NOT to use VC++ 6.0. It (and earlier versions) wer non-compliant in so many ways.
Correct. Unfortunately, we were using VC 6.0 at the time we went straight to the C++ Builder port of the code. This was around 6 years ago.
Regards,
Paul McKenzie