Well, I spent a day homing in on a bug and that's exactly what it
turned out to be.
Here's a Visual C++ compiler bug demonstrated in an 11-line program.
/////////////////////////////////////////////////////////////////
#include <iostream>
void CountDown(unsigned int j)
{
for(unsigned int i = j-1; i+1>0; --i)
cout << i << endl;
}
int main(int argc, char* argv[])
{
CountDown(4);
return 0;
}
///////////////////////////////////////////
In a debug build, the output is:
3
2
1
0
Which you'd expect.
In a release build, the output is:
3
Another round of Microsoft-bashing, anyone?
--
We are what we repeatedly do.
Excellence then, is not an act but a habit.
- Aristotle
Sent via Deja.com
http://www.deja.com/
This doesn't compile on my version. It MUST be
std::cout << i << std::endl;
Are you sure you have the latest compiler?
> }
>
> int main(int argc, char* argv[])
> {
> CountDown(4);
> return 0;
> }
> ///////////////////////////////////////////
>
> In a debug build, the output is:
>
> 3
> 2
> 1
> 0
>
> Which you'd expect.
> In a release build, the output is:
>
> 3
I don't know what FLAGS you used or what version you're on, but
my copy of VC++ produced the SAME output for both Debug and
Release verions. Could it be it's time for you to upgrade your
compiler?
Victor
--
Please remove capital A's from my address when replying by mail
Sorry, my mistake in copying the code to the message.
It required the "std::" in mine as well.
>
> I don't know what FLAGS you used or what version you're on, but
> my copy of VC++ produced the SAME output for both Debug and
> Release verions. Could it be it's time for you to upgrade your
> compiler?
I'm using Visual C++ 6.0 Enterprise Edition.
My version of CL.EXE is: 12.0.8804.0
Is that the same as yours?
Here are the compile settings for the release build:
Compile flags:
/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS"
/Fp"Release/CompilerBug.pch" /YX /Fo"Release/" /Fd"Release/" /FD /c
I have the same version as you and the same flags but it works on my
machine, strange.
john
The above code (after inserting a using directive) produces the same
behavior on my version:
VC++ 6.0 Professional
CL.EXE version = 12.0.8804.0
Release Project Options:
/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"
/D "_MBCS" /Fp"Release/test.pch" /YX /Fo"Release/" /Fd"Release/" /FD /c
Debug Project Options:
/nologo /MLd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"
/D "_MBCS" /Fp"Debug/test.pch" /YX /Fo"Debug/" /Fd"Debug/" /FD /GZ /c
very strange...
RSMellow
<snip>
I read somewhere that MS builder would *optimize* your code for you and
separate the for loop.
so the builder would do something like
for(unsigned int i = j-1; i+1>0; --i);// <-
cout << i << endl;
because it thinks it is doing you a favour.
try doing,
for(unsigned int i = j-1; i+1>0; --i)
{
cout << i << endl;
}
It might sound stupid but it might work.
http://www.myoddweb.com
It did not change the behavior for me.
RSMellow
Andrew Shepherd wrote:
> for(unsigned int i = j-1; i+1>0; --i)
If i is unsigned, wouldn't i+1 always be greater than 0?
Or am I as confused as your compiler?
Les
Actually, it will stop eventually. Assuming an unsigned int is a 32-bit
value on your architecture... 0xFFFFFFFF + 1 == 0x00000000. However,
personally, I would reword the boolean expression to be (i != 0) just to
avoid these roll-over conditions.
Think what happens to i when it is zero, and -- is applied
to it. Unsigned, it "wraps" to all bits turned on. Then
you add 1 to that, you get 0.
--
grelbr
Free insults!
> Think what happens to i when it is zero, and -- is applied
> to it. Unsigned, it "wraps" to all bits turned on. Then
> you add 1 to that, you get 0.
I see that behaviour when I step through VC++ code with the debugger.
But is it "defined behaviour"? Are compiler's "supposed" to do it this
way?
Putting the question as a code example:
unsigned int i = 0;
--i; // Decremented beyond its boundary
ASSERT((i+1)==0); // IS THIS IS A SAFE ASSERTION?
(Darn it, I think we might have to let Microsoft off the hook on this
one. :-) )
--
We are what we repeatedly do.
Excellence then, is not an act but a habit.
- Aristotle
Yes, it is. The result of any arithmetic operation with an unsigned
is brought to (result mod (UINT_MAX+1)). See 4.7 Integral conversions.
> Putting the question as a code example:
>
>
> unsigned int i = 0;
> --i; // Decremented beyond its boundary
> ASSERT((i+1)==0); // IS THIS IS A SAFE ASSERTION?
It better be.
From a post in news:microsoft.public.vc.ide_general:
:>??
:>This behavior was reported in a post to comp.lang.c++ and my test
exhibited
:>the same behavior. What could be the problem? There were others who posted
:>that they used the same settings and could not reproduce the behavior??
:>Does this seem strange to anyone else?
:
:It's an optimizer bug. If you replace:
:
:> for(unsigned int i = j-1; i+1>0; --i)
:
:with:
:
:> for(unsigned int i = j-1; i+1; --i)
:
:it works in VC6, SP4. An unsigned integer can never be less than zero,
:and the latter tests that it is not equal to zero, which is what you
:really want to do. However, both should have the same result. The
:VC.NET beta gets it right either way. Below are a couple of other ways
:to express the loop which work with VC6:
:
: for (unsigned i = j-1; i != -1; --i)
: for (unsigned i = j; i--; )
:
:I find both of those clearer.
:
:--
:Doug Harrison [VC++ MVP]
:Eluent Software, LLC
:http://www.eluent.com
:Tools for Visual C++ and Windows
:
HTH
RSMellow
gre...@my-deja.com wrote:
> > > for(unsigned int i = j-1; i+1>0; --i)
> >
> > If i is unsigned, wouldn't i+1 always be greater than 0?
> > Or am I as confused as your compiler?
>
> Think what happens to i when it is zero, and -- is applied
> to it. Unsigned, it "wraps" to all bits turned on. Then
> you add 1 to that, you get 0.
The "Compiler error?" topic in microsoft.public.vc.mfc states
that the optimizer basically made the same mistake that I did. :-)
The i+1>0 gets changed to i>-1. That may be always true or
never true depending upon what variables/values keep their signs.
Turn off the optimizer or rewrite the code to show what you
really meant.
Les