Help: Is this a bug in my compiler?

  • Thread starter mehrdad ghassempoory
  • Start date
M

mehrdad ghassempoory

I am using GCC version 4.3.2, I have an example program
shown below:

XXXXXXXXXXXXXXXXXXXX START XXXXXXXXXXXXXXXXXXXXX
#include <stdio.h>
main()
{
int i, j;
i=1;
i=3 + i++;
fprintf(stdout, "i=%d\n", i);
i=1;
j=3 + i++;
fprintf(stdout, "j=%d\n", j);
return 0;
}
XXXXXXXXXXXXXXXXXXXXX END XXXXXXXXXXXXXXXXXXXXXX

The program prints:

i=5
j=4


Is this a bug? If not, then can someone kindly
explain what is going on?

Many thanks in advance for your help.
 
B

Ben Pfaff

mehrdad ghassempoory said:
i=3 + i++;

This is a number of FAQs.

3.1: Why doesn't this code:

a = i++;

work?

A: The subexpression i++ causes a side effect -- it modifies i's
value -- which leads to undefined behavior since i is also
referenced elsewhere in the same expression, and there's no way
to determine whether the reference (in a on the left-hand
side) should be to the old or the new value. (Note that
although the language in K&R suggests that the behavior of this
expression is unspecified, the C Standard makes the stronger
statement that it is undefined -- see question 11.33.)

References: K&R1 Sec. 2.12; K&R2 Sec. 2.12; ISO Sec. 6.3; H&S
Sec. 7.12 pp. 227-9.

3.2: Under my compiler, the code

int i = 7;
printf("%d\n", i++ * i++);

prints 49. Regardless of the order of evaluation, shouldn't it
print 56?

A: Although the postincrement and postdecrement operators ++ and --
perform their operations after yielding the former value, the
implication of "after" is often misunderstood. It is *not*
guaranteed that an increment or decrement is performed
immediately after giving up the previous value and before any
other part of the expression is evaluated. It is merely
guaranteed that the update will be performed sometime before the
expression is considered "finished" (before the next "sequence
point," in ANSI C's terminology; see question 3.8). In the
example, the compiler chose to multiply the previous value by
itself and to perform both increments afterwards.

The behavior of code which contains multiple, ambiguous side
effects has always been undefined. (Loosely speaking, by
"multiple, ambiguous side effects" we mean any combination of
++, --, =, +=, -=, etc. in a single expression which causes the
same object either to be modified twice or modified and then
inspected. This is a rough definition; see question 3.8 for a
precise one, and question 11.33 for the meaning of "undefined.")
Don't even try to find out how your compiler implements such
things (contrary to the ill-advised exercises in many C
textbooks); as K&R wisely point out, "if you don't know *how*
they are done on various machines, that innocence may help to
protect you."

References: K&R1 Sec. 2.12 p. 50; K&R2 Sec. 2.12 p. 54; ISO
Sec. 6.3; H&S Sec. 7.12 pp. 227-9; CT&P Sec. 3.7 p. 47; PCS
Sec. 9.5 pp. 120-1.

3.3: I've experimented with the code

int i = 3;
i = i++;

on several compilers. Some gave i the value 3, and some gave 4.
Which compiler is correct?

A: There is no correct answer; the expression is undefined. See
questions 3.1, 3.8, 3.9, and 11.33. (Also, note that neither
i++ nor ++i is the same as i+1. If you want to increment i,
use i=i+1, i+=1, i++, or ++i, not some combination. See also
question 3.12.)
 
A

Alan Curry

I am using GCC version 4.3.2

and you should have used -Wall, and it would have told you this was bad.
i=3 + i++;

junk.c:6: warning: operation on 'i' may be undefined

In gcc 5, the -Wall warnings will be default warnings and the -Wextra
warnings will be promoted to -Wall.


Oh wait that was just a dream I had. :)
 
N

Nick

In gcc 5, the -Wall warnings will be default warnings and the -Wextra
warnings will be promoted to -Wall.

Finally! I've felt for many years that the default warning level on
many compilers is far, far too low.
 
N

Nick

Yes. Shame!

That's the first time I've encountered a genuine old-fashioned ^L for
spoiler space, and didn't understand what was going on.

It ought to be the case though. If I've got a big old project and it
breaks, then I just have to learn to set my warnings. What harm would
it do.

After all, those of us who do have the warnings turned on can find our old
code won't compile when they upgrade. So why no everyone else?
 
A

Alan Curry

Yes. Shame!

That's the first time I've encountered a genuine old-fashioned ^L for
spoiler space, and didn't understand what was going on.

That was *so* what I was hoping would happen. Get everyone's hopes up, then
let you down... and the memory of how good it felt to believe would create a
movement to make it real.

The "operation may be undefined" warning is pretty new (at least I didn't
notice it until recently) but I happen to have the exact same version the
original poster mentioned, and it did spit out a warning with -Wall.

I didn't say -Werror was default in my false-hope future, so bad code would
still compile, it would just be noisier.
 
K

Keith Thompson

Nick said:
Yes. Shame!

That's the first time I've encountered a genuine old-fashioned ^L for
spoiler space, and didn't understand what was going on.

It ought to be the case though. If I've got a big old project and it
breaks, then I just have to learn to set my warnings. What harm would
it do.

After all, those of us who do have the warnings turned on can find our old
code won't compile when they upgrade. So why no everyone else?

In at least some cases, GNU autoconf assumes that, if the compiler
produces any output on stderr, the compilation failed. Specifically,
it checks for the existence of headers by compiling a small generated
program that includes those headers; if the compilation generates
anything on stderr, autoconf assumes the headers don't exist.

Thus increasing the default warning level could break existing code,
and since the breakage isn't in the user's code, fixing it could
be difficult.

For an example of this kind of problem, see
<http://users.sdsc.edu/~kst/gcc-wrapper/>. (I'm no longer at SDSC,
so don't bother contacting me via the address on the page.)
 
S

Seebs

In at least some cases, GNU autoconf assumes that, if the compiler
produces any output on stderr, the compilation failed. Specifically,
it checks for the existence of headers by compiling a small generated
program that includes those headers; if the compilation generates
anything on stderr, autoconf assumes the headers don't exist.

Hmm. Are you sure? I ask because I work a lot with a gcc-based compiler
which, under some likely circumstances, can emit a message to stderr
on EVERY POSSIBLE INVOCATION. Bar none. And out of a hundred and some
packages I built, only one blew up on this -- I think it was zlib, which
was using the existence of any messages on stderr as evidence of "failure".

I think autoconf is supposed to be checking the creation of output files
or something.

(BTW, rumor has it that gcc 4.5 will actually abort on a missing header,
rather than trying to continue. This is because I work at a company that
has a support contract for gcc, and after getting bitten by the current
behavior once too often, I filed an enhancement request.)

-s
 
S

Seebs

i=1;
i=3 + i++;
The value of i is either 4 or 5 due to different compiler!

Or anything else it wants to be. The behavior is undefined. It isn't
even guaranteed, in at least some cases, to compile.

-s
 
N

Nick

Keith Thompson said:
In at least some cases, GNU autoconf assumes that, if the compiler
produces any output on stderr, the compilation failed. Specifically,
it checks for the existence of headers by compiling a small generated
program that includes those headers; if the compilation generates
anything on stderr, autoconf assumes the headers don't exist.

Thus increasing the default warning level could break existing code,
and since the breakage isn't in the user's code, fixing it could
be difficult.

For an example of this kind of problem, see
<http://users.sdsc.edu/~kst/gcc-wrapper/>. (I'm no longer at SDSC,
so don't bother contacting me via the address on the page.)

Obviously there's a versions problem, but can't autoconf call gcc with
the (new) "--accept-horrible-code" flag?
 
K

Keith Thompson

Seebs said:
Hmm. Are you sure? I ask because I work a lot with a gcc-based compiler
which, under some likely circumstances, can emit a message to stderr
on EVERY POSSIBLE INVOCATION. Bar none. And out of a hundred and some
packages I built, only one blew up on this -- I think it was zlib, which
was using the existence of any messages on stderr as evidence of "failure".

I think autoconf is supposed to be checking the creation of output files
or something.

Well, I'm sure that with the version of autoconf being used at the
time (5+ years ago) on the particular software package (Globus),
a spurious warning message was causing autoconf to incorrectly
conclude that certain headers didn't exist, and either hacking
gcc to remove the warning or using a wrapper that discarded it
worked around the problem. Perhaps the real problem was with the
configuration files being used for that package.
(BTW, rumor has it that gcc 4.5 will actually abort on a missing header,
rather than trying to continue. This is because I work at a company that
has a support contract for gcc, and after getting bitten by the current
behavior once too often, I filed an enhancement request.)

Why would that bite you? gcc 4.3.3 prints an error message for a
missing header; it continues with the rest of the translation unit,
but it ultimately rejects it. You can get a whole lot of meaningless
diagnostics (if you misspell <stdio.h>, you'll get diagnostics on
every I/O call), but that shouldn't be fatal. Though I agree (mostly)
that once you've encountered a missing header there's not much point
in continuing.
 
S

Seebs

Why would that bite you?
You can get a whole lot of meaningless diagnostics

Yes, you can. Thousands of lines of them.
but that shouldn't be fatal.

In context: We have a build system which builds packages with output
and errors into log files. We then display the last N lines of a log
file on a failure. Which means that the current behavior ensures that
a missing header cannot be diagnosed without going and looking at the
full log file, while the corrected behavior would allow it to be diagnosed
instantly.
Though I agree (mostly)
that once you've encountered a missing header there's not much point
in continuing.

I have never yet had a case where continuing was rewarding. I have had
hundreds where sorting through the irrelevant error messages was a pain
or caused me trouble.

-s
 
B

Ben Pfaff

Seebs said:
(BTW, rumor has it that gcc 4.5 will actually abort on a missing header,
rather than trying to continue. This is because I work at a company that
has a support contract for gcc, and after getting bitten by the current
behavior once too often, I filed an enhancement request.)

It's more than a rumor. See the first bullet under "C Family" at
http://gcc.gnu.org/gcc-4.5/changes.html
 
K

Keith Thompson

Seebs said:
Yes, you can. Thousands of lines of them.


In context: We have a build system which builds packages with output
and errors into log files. We then display the last N lines of a log
file on a failure. Which means that the current behavior ensures that
a missing header cannot be diagnosed without going and looking at the
full log file, while the corrected behavior would allow it to be diagnosed
instantly.

Perhaps you should be looking at the *first* N lines of the log file,
or use some smarter algorithm that shows the first few diagnostics.

A missing header is probably the most obvious cause of a cascade of
spurious diagnostics, but it's not the only one.
I have never yet had a case where continuing was rewarding. I have had
hundreds where sorting through the irrelevant error messages was a pain
or caused me trouble.

Sorting through things is something computers can be very good at.
 
S

Seebs

Perhaps you should be looking at the *first* N lines of the log file,
or use some smarter algorithm that shows the first few diagnostics.

It's surprisingly hard. Not all diagnostics are compiler diagnostics,
or otherwise recognizeable as such, so you'd need a complete list of all
possible error messages, which you don't have.
A missing header is probably the most obvious cause of a cascade of
spurious diagnostics, but it's not the only one.

True. Of course, in the other cases, the cause may not be identifiably
a diagnostic at all.

-s
 

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
474,432
Messages
2,571,682
Members
48,796
Latest member
Greg L.

Latest Threads

Top