Sign in to follow this  
nivlekio

C++ Bug????

Recommended Posts

I was working on networking and i made a silly mistake.
Quote:
while(1); { cout << "In while Loop" << endl if(argument) { code........ } else { break; } }
As you can see there is a semi colon after the while command. Some how this made the program loop forever at the while(1) bit and not execute the code in the braces. I know this becuase it did not print out the "In while Loop" string. But after i noticed this mistake ( 2hrs later :( ) i took off the semi colon and the program entered the while loop braces and executed the code. then it broke out of it then the if statement was false. Seeing i did not get an error from the compiler why would some one want to do this if its proper c++ code?

Share this post


Link to post
Share on other sites
Quote:
Some how this made the program loop forever at the while(1) bit and not execute the code in the braces. I know this becuase it did not print out the "In while Loop" string.

Of course, because while(1); is an infinity loop.

Quote:
Seeing i did not get an error from the compiler why would some one want to do this if its proper c++ code?


Because C and C++ do not have any strict rules on how you format your code. ; is used to end a statement (in your case, while(1)), which has caused the infinity loop.

Because there is no strict formatting rules, it allows us to write a given statement different ways.

Also, because { and } are used for creating a new local scope, there is no errors in your code--with or without the semicolen (;).

Share this post


Link to post
Share on other sites
Newer versions of GCC warn on this kind of construct as it's very dangerous and easily overlooked. Have found this bug in somebody elses javascript as well.

GCC now requires you (if you enable the warnings) to write

while(1) {}

as it will refuse the semicolon for such use.

Share this post


Link to post
Share on other sites
I've often seen such statements coded as:


while(statement_is_true)
;




It makes it look more like an if statement with one following line without braces. Just a blank line in this case.

Although a lot of people aren't so fond of using whiles or ifs without any braces. Which makes sense. Not using braces has hurt me before. (Well I guess I hurt myself because I wasn't paying attention).

Share this post


Link to post
Share on other sites
Quote:
Original post by ToohrVyk
size_t strlen(const char *s)
{
size_t i = 0;
while (s[i++] != '\0');
return i - 1;
}



size_t strlen(const char *s)
{
size_t i = 0;
while (s[i] != 0) i++;
return i;
}



faster?

Share this post


Link to post
Share on other sites
Quote:
Original post by staticVoid2
Quote:
Original post by ToohrVyk
size_t strlen(const char *s)
{
size_t i = 0;
while (s[i++] != '\0');
return i - 1;
}


*** Source Snippet Removed ***

faster?
It'll generate the exact same assembly, so no.

Share this post


Link to post
Share on other sites
Quote:
Original post by staticVoid2
Quote:
Original post by ToohrVyk
size_t strlen(const char *s)
{
size_t i = 0;
while (s[i++] != '\0');
return i - 1;
}

size_t strlen(const char *s)
{
size_t i = 0;
while (s[i] != 0) i++;
return i;
}

faster?

How about with a pre-increment for those elusive extra cycles... [grin]
size_t strlen(const char *s)
{
size_t i = -1;
while (s[++i] != 0);
return i;
}

Share this post


Link to post
Share on other sites
How 'bout we just use the strlen that came with the compiler, which is implemented in carefully hand-tuned assembly and is blazingly fast.

Share this post


Link to post
Share on other sites
Quote:
How about with a pre-increment for those elusive extra cycles...

Postincrement will be optimized by the compiler automatically for builtin types, as per Sutter.

Share this post


Link to post
Share on other sites
Let's be brutally honest here .. the built in strlen is fast enough for any situation you can think of; and trusting your compiler to generate better code than hand tuned assembly is madness. No offense. :-) Though if you want to take it to the next level then let's start another thread and lay some hard performance metrics down comparing the strlen provided by your favourite compiler vendor and our own implementations :-) Otherwise, let's just leave poor old strlen alone, what did he ever do to you anyway?

Share this post


Link to post
Share on other sites
I've been programming on and off for 12 years and have seen a grand total of 4 genuine, verified bugs in interpreters / compilers. The other 1.2E97 errors were my fault.

Still, its fair to say that while(); should not be standard, and should at the very least generate a warning, but that is a design choice and not a "bug" as such.

Share this post


Link to post
Share on other sites
Quote:
Original post by speciesUnknown
I've been programming on and off for 12 years and have seen a grand total of 4 genuine, verified bugs in interpreters / compilers. The other 1.2E97 errors were my fault.


You're lucky. I've seen dozens, and I've personally tracked down at least 10 (producing reliable test-cases for the vendors). The joys of console development.

Share this post


Link to post
Share on other sites
Quote:
Original post by osmanb
Quote:
Original post by speciesUnknown
I've been programming on and off for 12 years and have seen a grand total of 4 genuine, verified bugs in interpreters / compilers. The other 1.2E97 errors were my fault.


You're lucky. I've seen dozens, and I've personally tracked down at least 10 (producing reliable test-cases for the vendors). The joys of console development.


I've also tracked down a few from vendors over the years. They are rare but they do happen. The smaller the audience the more likely you are to find them, which is why console and embedded programmers complain so much about the low quality of the tools. Almost everything I've seen over the last five or eight years has been many orders of magnitude better than the older compilers. We used to just have the AT&T c++ specs to claim violations, but often those cries fell on deaf ears. Being able to point at an ISO standard has really helped every serious compiler out there.

Just beware.

Unless you have real proof that it is wrong, don't go blaming the compiler.

Remember that thousands or tens-of-thousands of people around the globe are using those tools. The odds of you discovering a major bug are extremely small. It is much more likely that it is a fault in your own code. If you are saying something like "The STL is broken" you are probably wrong. If it is something like "a particular combination of function pointers inside an anonymous union doesn't seem to work properly", then you may be on to something.


In the case of a crash, you should be prepared with output of an actual compiler crash or ICE along with source that they can use to reproduce it. Those are easy to spot.

Often people claim: "You have a bug that such-and-such didn't do what I expected". They are often immediately countered with short replies like: "See the language standard, section 6.x.y paragraph 4. The behavior you saw is correct." When you make a claim, you better be able to show exactly what the problem is, a short code sample that demonstrates it, and the exact place in the language standard that says it is wrong.

In the case of debug vs released/optimized code, it is often harder to prove a compiler error. You have to prove that your optimizations were incorrectly applied, and not the result of a correctly acting but misapplied optimizer. The most common non-bug I've seen is aggressive dead code removal -- if you aren't directly accessing a function the optimizer may (legitimately) see it as dead code and remove it. When you start getting fancy with the language, carefully watch the verbose compiler and linker outputs before claiming it is a bug.


It's okay to claim you found a bug. Just be prepared to prove it.

Share this post


Link to post
Share on other sites
This is indeed legal code. In C, the semicolon is used to terminate all expressions but it's also used alone as the empty expression. As pointed out by others, there are indeed "useful" applications of the empty expression and the while statement but it's more often a typo. Even if it's not a typo, it's misleading and cryptic syntax that should at least generate a warning.

MSVC++ 2008 doesn't generate a warning even on warning level 4. It does generate a warning about while(1) itself though, apparently conditional expressions shouldn't be constants. If you want to use infinite loops on warning level 4, I guess you have to use for(;;).

To answer questions like this, it's usually best to go to raw information. That information being the ANSI C standard or a C grammar in this case.

Share this post


Link to post
Share on other sites
Quote:
Original post by osmanb
You're lucky. I've seen dozens, and I've personally tracked down at least 10 (producing reliable test-cases for the vendors). The joys of console development.


Ahh I was skeptical until I saw the username! We don't know each other, but as of recently I work for the same company as you (large version), and I've long been a fan of your posts on platform support groups. (It's possible you'd recognize my real name in the same way, but it's hard to say.)

Nice to know that you post here as well.

Share this post


Link to post
Share on other sites
Quote:
Original post by UziMonkey
This is indeed legal code. In C, the semicolon is used to terminate all expressions but it's also used alone as the empty expression.


Hmm? No, the empty expression is represented by a sequence of zero tokens. The semicolon just terminates it. ;)

Anyway, this is one place where there's arguably a clear advantage for putting open braces at the end of a line. Simply put, ";{" looks wrong (and is kind of hard to type).

Quote:
MSVC++ 2008 doesn't generate a warning even on warning level 4. It does generate a warning about while(1) itself though, apparently conditional expressions shouldn't be constants. If you want to use infinite loops on warning level 4, I guess you have to use for(;;).


I kinda wish the language offered an explicit construct for this. (My language design includes one: 'until <expr>' is a synonym for 'while not(<expr>)', and then 'until break' is also allowed as a special case, meaning an infinite loop.)

Quote:
To answer questions like this, it's usually best to go to raw information. That information being the ANSI C standard or a C grammar in this case.


Best in terms of accuracy, sure, but maybe not in terms of clarity. :)

Share this post


Link to post
Share on other sites
Quote:
Original post by staticVoid2
its funny how visual c++ will throw a warning when you put

if(condition);

but not when you put

while(1);

Because no matter what the condition is in the if statement (could be a function call), it is always going to be useless. As pointed out in the examples above, the while loop can have his uses if the condition isn't constant (and apparently it does yield a warning at level 4 for constant expressions).

Share this post


Link to post
Share on other sites
Quote:
Original post by WanMaster
Quote:
Original post by staticVoid2
its funny how visual c++ will throw a warning when you put

if(condition);

but not when you put

while(1);

Because no matter what the condition is in the if statement (could be a function call), it is always going to be useless. As pointed out in the examples above, the while loop can have his uses if the condition isn't constant (and apparently it does yield a warning at level 4 for constant expressions).


thats why I put while(1); and not while(condition); I can't see any use for while(1); but I wouldn't use any compiler that didn't allow it.

Share this post


Link to post
Share on other sites
Quote:
Original post by staticVoid2
I can't see any use for while(1); but I wouldn't use any compiler that didn't allow it.


Oh ye of limited imagination. (1) working a kernel thread scheduling system. An infinite busy wait can just be what the doctor ordered for testing to see if your system does in fact more or less evenly schedules the load. (Or unevenly for thread priorities as the case may be.) (2) Some embedded systems will power down if the process finishes executing. So if there's a fatal error that the user needs to see: display the error message and then go into an infinite loop. (3) learning assembly language via compiler output. Want to know what kind of assembly is used for generating a non conditional jump on a platform? Put while(1); in a function and feed it to a compiler with -S or /FAs or whatever switch spits out assembly. (4) testing the program flow analysis of a compiler. Want to see if a new compiler will warn you about unreachable code? Stick a statement after a while(1); and see what kind of warnings the compiler will spit out. (5) Writing a tutorial on debugging? while(1); might be part of a code example or exercise demonstrating the use of breaking into an executing program.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this