Horrible Visual C Bug!

O

Oliver Brausch

Hello,

have you ever heard about this MS-visual c compiler bug?
look at the small prog:


static int x=0;
int bit32() {
return ++x;
}

int bit64() {
return bit32() + (bit32() << 1);
}

void main(int argc, char **argv) {
int i;
for (i = 0; i < 5; i++) printf("%d. %d\n", i, bit64());
}


Ok, the (correct) result is:

0. 2
1. 8
2. 14
3. 20
4. 26

This is what every compiled progam says. Inclusive MSVisualC Compiler
with Debug options or /Ot fast-option.

But do not dare to switch to the the /O2 option of MSVisualC Compiler.
Then once your computer cannot calculate anymore:

0. 1
1. 7
2. 13
3. 19
4. 25

So, up to Microsoft, 0 + 2 = 1 ?????. That's why their OS is so stable....
Try to increase the "<< 1". It even gets worse.

Ever seen this? I costed me hours of debugging. Can I
sue Microsoft for this?

- Oliver Brausch

http://home.arcor.de/dreamlike
 
J

Jakob Bieling

have you ever heard about this MS-visual c compiler bug?
look at the small prog:

It is not a compiler bug. It is a bug in your code.
static int x=0;
int bit32() {
return ++x;
}

int bit64() {
return bit32() + (bit32() << 1);
}

You try to change a variable twice, which is invalid, ie. undefined
behaviour. Microsoft's compiler is absolutely right.
void main(int argc, char **argv) {

'void main' is illegal. It is *always* 'int main'.
int i;
for (i = 0; i < 5; i++) printf("%d. %d\n", i, bit64());
}
This is what every compiled progam says. Inclusive MSVisualC Compiler
with Debug options or /Ot fast-option.

So? Just because many compiled programs say this should be the result
does not mean that they are right.
> Ever seen this? I costed me hours of debugging. Can I
sue Microsoft for this?

No, but your boss could fire you for such C code, since it is invalid.
 
J

Joona I Palaste

Oliver Brausch <[email protected]> scribbled the following
have you ever heard about this MS-visual c compiler bug?
look at the small prog:

static int x=0;
int bit32() {
return ++x;
}
int bit64() {
return bit32() + (bit32() << 1);

These two bit32() calls can be evaluated in either order, and the
implementation doesn't even have to be consistent about it.

Assume x==0. The first way:
bit32() + (bit32() << 1) ==
1 + (bit32() << 1) ==
1 + (2 << 1) ==
1 + (4) ==
5
The second way:
bit32() + (1 << 1) ==
bit32() + (2) ==
2 + (2) ==
4
void main(int argc, char **argv) {

You have induced undefined behaviour by using void main() and lost all
right to expect any kind of specific behaviour at all.
int i;
for (i = 0; i < 5; i++) printf("%d. %d\n", i, bit64());
}

Ok, the (correct) result is:

Anything. Any result is correct, because of the void main().
0. 2
1. 8
2. 14
3. 20
4. 26
This is what every compiled progam says. Inclusive MSVisualC Compiler
with Debug options or /Ot fast-option.
But do not dare to switch to the the /O2 option of MSVisualC Compiler.
Then once your computer cannot calculate anymore:
0. 1
1. 7
2. 13
3. 19
4. 25

You'll have to read up on undefined behaviour (void main()) and
unspecified behaviour (bit32() + (bit32() << 1)).
So, up to Microsoft, 0 + 2 = 1 ?????. That's why their OS is so stable....
Try to increase the "<< 1". It even gets worse.
Ever seen this? I costed me hours of debugging. Can I
sue Microsoft for this?

No. It's neither their or C's fault. It's yours.

--
/-- Joona Palaste ([email protected]) ---------------------------\
| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.helsinki.fi/~palaste W++ B OP+ |
\----------------------------------------- Finland rules! ------------/
"There's no business like slow business."
- Tailgunner
 
A

Artie Gold

Oliver said:
Hello,

have you ever heard about this MS-visual c compiler bug?
Nope.

look at the small prog:
OK...

static int x=0;
int bit32() {
return ++x;
}

int bit64() {
return bit32() + (bit32() << 1);
}

void main(int argc, char **argv) {
int main(int argc, char **argv) {

but since you're not making use of the command-line interface,

int main(void)

would do quite nicely...
int i;
for (i = 0; i < 5; i++) printf("%d. %d\n", i, bit64());
}


Ok, the (correct) result is:

0. 2
1. 8
2. 14
3. 20
4. 26

Oh, really?

What if I told you that the correct result could be just about anything,
including demons flying out of your nose?
This is what every compiled progam says. Inclusive MSVisualC Compiler
with Debug options or /Ot fast-option.

But do not dare to switch to the the /O2 option of MSVisualC Compiler.
Then once your computer cannot calculate anymore:

0. 1
1. 7
2. 13
3. 19
4. 25

So, up to Microsoft, 0 + 2 = 1 ?????. That's why their OS is so stable....
Try to increase the "<< 1". It even gets worse.

Well, as it turns out, the bug is on the other side of the keyboard in
this case.[1]

Please see: http://www.eskimo.com/~scs/C-faq/s3.html for an explanation.
Ever seen this? I costed me hours of debugging. Can I
sue Microsoft for this?

Actually, even if it had been their bug (which it isn't) you couldn't --
read the license.

HTH,
--ag

[1] Not that I would mind a bit had it been _their_ fault.
 
B

Brett Frankenberger

You try to change a variable twice, which is invalid, ie. undefined
behaviour.

There is a sequence point between the two modifications of x, so
there's no undefined behavior here. The C language doesn't specify
which of the two bit32()'s will be invoked first, so there is
unspecified behavior here. But the first two calls to bit32() are
going to return 1 and 2 respectively, giving:
1 + (2 << 1) which is 5, or
2 + (1 << 1) which is 4
for the first return of bit64(). (If this were undefined behavior, the
compiler would be free to do whatever it wanted. That's not the case
here -- he can reliably assume he'll get 4 or 5 ... he just can't
assume which one he'll get.)

(The two outputs he shows (1 and 2 for the first call to bit64())
aren't possible from the code he posted ... but I assume his test code
actually had "x++" instead of "++x".)

-- Brett
 
J

Joona I Palaste

Brett Frankenberger <[email protected]> scribbled the following
There is a sequence point between the two modifications of x, so
there's no undefined behavior here. The C language doesn't specify
which of the two bit32()'s will be invoked first, so there is
unspecified behavior here. But the first two calls to bit32() are
going to return 1 and 2 respectively, giving:
1 + (2 << 1) which is 5, or
2 + (1 << 1) which is 4
for the first return of bit64(). (If this were undefined behavior, the
compiler would be free to do whatever it wanted. That's not the case
here -- he can reliably assume he'll get 4 or 5 ... he just can't
assume which one he'll get.)
(The two outputs he shows (1 and 2 for the first call to bit64())
aren't possible from the code he posted ... but I assume his test code
actually had "x++" instead of "++x".)

Actually, yes they are. He has undefined behaviour - void main(). 1 and
2 are as legal outputs as 4 and 5, and so is "your mother was a hamster
and your father smelt of elderberries".

--
/-- Joona Palaste ([email protected]) ---------------------------\
| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.helsinki.fi/~palaste W++ B OP+ |
\----------------------------------------- Finland rules! ------------/
"Life without ostriches is like coffee with milk."
- Mika P. Nieminen
 
B

Brett Frankenberger

Brett Frankenberger <[email protected]> scribbled the following



Actually, yes they are. He has undefined behaviour - void main(). 1 and
2 are as legal outputs as 4 and 5, and so is "your mother was a hamster
and your father smelt of elderberries".

Yes, of course, but I wasn't responding to that. I was responding to
the claim that calling bit32() twice, as shown above, was undefined
behavior. And it's not. I specifically didn't show the void main()
part of the code.

As a practical matter, if he fixed the void main() thing, he's not
going to get a different result -- he'll still get one of the two
possible outcomes from bit64(). So he'll end up with a program that
has unspecified (but not undefined) behavior.

-- Brett
 
T

Thore B. Karlsen

No, it is not. However, int main has always been considered MUCH better
practice, because it allows for escapes and return codes.

No, it's illegal. Read the standards.
 
J

Jakob Bieling

Falcon Kirtarania said:
No, it is not. However, int main has always been considered MUCH better
practice, because it allows for escapes and return codes.

You might want to do a search on Google about why you should write 'int
main' instead of 'void main'. Do not want to start such a long discussion
again. ;o)

regards
 
C

Christian Bau

Hello,

have you ever heard about this MS-visual c compiler bug?
look at the small prog:


static int x=0;
int bit32() {
return ++x;
}

int bit64() {
return bit32() + (bit32() << 1);
}

void main(int argc, char **argv) {
int i;
for (i = 0; i < 5; i++) printf("%d. %d\n", i, bit64());
}


Ok, the (correct) result is:

0. 2
1. 8
2. 14
3. 20
4. 26

This is what every compiled progam says. Inclusive MSVisualC Compiler
with Debug options or /Ot fast-option.

But do not dare to switch to the the /O2 option of MSVisualC Compiler.
Then once your computer cannot calculate anymore:

0. 1
1. 7
2. 13
3. 19
4. 25

So, up to Microsoft, 0 + 2 = 1 ?????. That's why their OS is so stable....
Try to increase the "<< 1". It even gets worse.

Ever seen this? I costed me hours of debugging. Can I
sue Microsoft for this?

Unspecified behaviour. It is absolutely to be expected that two
compilers will give different results. And I would just guess that the
code you posted is not the one that produced this output anyway; maybe
bit32 () contained an x++ instead of a ++x? If you took a programming
course with Microsoft, then maybe you can demand your money back.
 
E

Emmanuel Delahaye

In said:
have you ever heard about this MS-visual c compiler bug?
look at the small prog:

static int x=0;
int bit32() {
return ++x;

I don't like that too much.

Do you meant?

int bit32()
{
static int x=0;

x++;
return x;
}
int bit64() {
return bit32() + (bit32() << 1);
}

Let's go by hand:

[0] 1 + (2 * 2) = 5
[1] 3 + (4 * 2) = 11
[2] 5 + (6 * 2) = 17
[3] 7 + (8 * 2) = 23
[4] 9 + (10 * 2) = 29

Dev-C++ (gcc) :

0. 5
1. 11
2. 17
3. 23
4. 29
void main(int argc, char **argv) {
int i;
for (i = 0; i < 5; i++) printf("%d. %d\n", i, bit64());
}


Ok, the (correct) result is:

0. 2
1. 8
2. 14
3. 20
4. 26

Why?
This is what every compiled progam says. Inclusive MSVisualC Compiler
with Debug options or /Ot fast-option.

But do not dare to switch to the the /O2 option of MSVisualC Compiler.
Then once your computer cannot calculate anymore:

0. 1
1. 7
2. 13
3. 19
4. 25

Wrong too. Sounds like a UB. I suspect a sequence point is missing in
 
J

Joona I Palaste

Emmanuel Delahaye <[email protected]> scribbled the following
In 'comp.lang.c', (e-mail address removed) (Oliver Brausch) wrote:
I don't like that too much.

Do you meant?
int bit32()
{
static int x=0;
x++;
return x;
}
Let's go by hand:
[0] 1 + (2 * 2) = 5
[1] 3 + (4 * 2) = 11
[2] 5 + (6 * 2) = 17
[3] 7 + (8 * 2) = 23
[4] 9 + (10 * 2) = 29
Dev-C++ (gcc) :
0. 5
1. 11
2. 17
3. 23
4. 29
Wrong too. Sounds like a UB. I suspect a sequence point is missing in

No, there is nothing wrong with "return ++x;" by itself. Not a missing
sequence point, anyway. Others have already explained the OP's problems
to him: (1) He's using void main(), undefined behaviour. (2) He's
calling bit32() twice without an intervening sequence point,
unspecified behaviour.

--
/-- Joona Palaste ([email protected]) ---------------------------\
| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.helsinki.fi/~palaste W++ B OP+ |
\----------------------------------------- Finland rules! ------------/
"You can pick your friends, you can pick your nose, but you can't pick your
relatives."
- MAD Magazine
 
N

Noah Roberts

Falcon said:
Yes, but it is still legal, in that it will compile. I am not saying void
main should be considered good practice, only that it is still compilable
and (for all intents and purposes) works, as long as you don't give a crap
about certain results.

Lots of things compile that are not standard or "illegal" by standard.

Still, I am stuck wondering why this is taking place in r.g.c.c

NR
 
J

Joona I Palaste

Falcon Kirtarania <[email protected]> scribbled the following
Any compiler I've used never called it.

You haven't used every compiler there is. And even if you had, nothing
would stop anyone from writing a new compiler where void main() was
illegal.
The moral of the story is: When the ISO C standard and your compiler
are giving you different ideas, trust the ISO C standard.

--
/-- Joona Palaste ([email protected]) ---------------------------\
| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.helsinki.fi/~palaste W++ B OP+ |
\----------------------------------------- Finland rules! ------------/
"I will never display my bum in public again."
- Homer Simpson
 
T

Thore B. Karlsen

Yes, but it is still legal, in that it will compile. I am not saying void
main should be considered good practice, only that it is still compilable
and (for all intents and purposes) works, as long as you don't give a crap
about certain results.

The fact that one or several compilers accepts a piece of code does not
mean it is legal code.
 
J

jemma

<snip>

Ever seen this? I costed me hours of debugging.

<snip>

Hours? If you've read all of the replies to your post and understand
what you've been told, that's not too bad considering all the lessons
you've (hopefully) learned -- and you'll be a better programmer (and
USENET poster) for it.

It's common for a novice programmer to blame the compiler, but
resist the temptation. Remember:

"...I don't think there is any question about it. It can only
be attributable to human error. This sort of thing has cropped
up before and it has always been due to human error."
--HAL 9000
 
F

Falcon Kirtarania

Perhaps not in ISO C, then. Whatever. As long as you don't need to port it
between compilers, it really doesn't matter.
 
F

Falcon Kirtarania

It does, as long as you are considering only the standards of those
compilers.
 
J

Jakob Bieling

Falcon Kirtarania said:
Yes, but it is still legal, in that it will compile.

'it will compile' and 'it is legal C or C++' are two different shoes.
I am not saying void
main should be considered good practice, only that it is still compilable

On the few compilers you have used, that might be true. It is also true
for the compiler I use. So what, it is still illegal.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top