Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Basic Compiler Error in Visual C++

10 views
Skip to first unread message

Andrew Shepherd

unread,
Jan 23, 2001, 9:24:20 PM1/23/01
to
Saying "Maybe it's a compiler error" usually provokes scorn and
derision.

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/

Victor Bazarov

unread,
Jan 23, 2001, 9:40:54 PM1/23/01
to
"Andrew Shepherd" <sheph...@my-deja.com> wrote...

> Saying "Maybe it's a compiler error" usually provokes scorn and
> derision.
>
> 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;

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

Andrew Shepherd

unread,
Jan 24, 2001, 12:34:54 AM1/24/01
to

>
> This doesn't compile on my version. It MUST be
>
> std::cout << i << std::endl;
>
> Are you sure you have the latest compiler?

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

John Harrison

unread,
Jan 24, 2001, 3:06:22 AM1/24/01
to

"Andrew Shepherd" <sheph...@my-deja.com> wrote in message
news:94lphv$bj4$1...@nnrp1.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?
>
> 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

RSMellow

unread,
Jan 24, 2001, 7:52:49 AM1/24/01
to
"Andrew Shepherd" <sheph...@my-deja.com> wrote in message
news:94lece$2gp$1...@nnrp1.deja.com...
: Saying "Maybe it's a compiler error" usually provokes scorn and

: derision.
:
: 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?

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


Florent

unread,
Jan 24, 2001, 8:31:41 AM1/24/01
to

>
> /////////////////////////////////////////////////////////////////
> #include <iostream>
>
> void CountDown(unsigned int j)
> {
> for(unsigned int i = j-1; i+1>0; --i)
> cout << i << endl;
> }

<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

RSMellow

unread,
Jan 24, 2001, 8:46:16 AM1/24/01
to
"Florent" <guel...@my-deja.com> wrote in message
news:94mlft$l1$1...@nnrp1.deja.com...
:
: >
: > /////////////////////////////////////////////////////////////////

It did not change the behavior for me.


RSMellow


Les Hammer

unread,
Jan 24, 2001, 10:46:38 AM1/24/01
to

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

Andre Kostur

unread,
Jan 24, 2001, 11:06:49 AM1/24/01
to
les_h...@agilent.com (Les Hammer) wrote in
<3A6EF8DE...@agilent.com>:

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.

gre...@my-deja.com

unread,
Jan 24, 2001, 11:59:23 AM1/24/01
to
In article <3A6EF8DE...@agilent.com>,

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!

Andrew Shepherd

unread,
Jan 24, 2001, 5:35:48 PM1/24/01
to

> 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


Victor Bazarov

unread,
Jan 24, 2001, 6:15:30 PM1/24/01
to
"Andrew Shepherd" <sheph...@my-deja.com> wrote...

>
>
> > 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?

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.

RSMellow

unread,
Jan 24, 2001, 7:30:26 PM1/24/01
to
"Andrew Shepherd" <sheph...@my-deja.com> wrote in message
news:94lece$2gp$1...@nnrp1.deja.com...
: Saying "Maybe it's a compiler error" usually provokes scorn and


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

Les Hammer

unread,
Jan 24, 2001, 7:34:40 PM1/24/01
to

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

0 new messages