Optimization Level -O2 in gcc

F

felipemartinsss

Hi Everybody.
I have a problem with the flag -O2 and I would like to know why this
problem is ocurring.
I have the following code:

#include <stdio.h>
int f3nPlus1 (int n, int count);

int main(void) {
/* Declaração de variáveis */
int n = 0;
int maximumCycle = 0;
int begin = 0;
int end = 0;
int temp = 0;
FILE *filePtr;

/* Código */

filePtr = fopen("a.in", "r");

if (filePtr) {
while (!feof(filePtr)) {
fscanf(filePtr, "%d%d\n", &begin, &end);
/*printf ("begin: %d\n", begin);
printf ("end: %d\n", end);*/
for (n = begin; n <= end; n++) {
temp = f3nPlus1( n, 0 );
/*printf ("temp: %d\n", temp);*/
if (temp > maximumCycle) {
maximumCycle = temp;
}

}
printf( "%d %d %d\n", begin, end, maximumCycle );
temp = 0;
maximumCycle = 0;

}
fclose(filePtr);

} else {
printf ("Arquivo nao pode ser aberto.\n");
}
return 0;
}

int f3nPlus1( int n, int count ) {
if( n == 1 ) {
return count + 1;
} else {
if(n % 2 != 0) {
n = 3 * n + 1;
f3nPlus1 ( n , count + 1);
} else {
n = n / 2;
f3nPlus1 ( n , count + 1);
}
}
}


When I compile the code with gcc -o f3nPlus1 f3nPlus1.c -lm -lcrypt -
pipe -ansi, everything's ok.
But, when I compile with gcc -O2 -o f3nPlus1 f3nPlus1.c -lm -lcrypt -
pipe -ansi, the execution give me wrong answers.

The contents of the file a.in are:
1 10
100 200
900 1000
1 10
1 11
12 13
1 10
100 200
201 210
900 1000

Thanks for the attention!
 
E

Eric Sosman

felipemartinsss said:
Hi Everybody.
I have a problem with the flag -O2 and I would like to know why this
problem is ocurring.
I have the following code:
[...]
while (!feof(filePtr)) {

This is not the problem you asked about, but it is
another error you will eventually need to fix. Please
see Question 12.2 in the comp.lang.c Frequently Asked
Questions (FAQ) list at said:
[...]
int f3nPlus1( int n, int count ) {
if( n == 1 ) {
return count + 1;
} else {
if(n % 2 != 0) {
n = 3 * n + 1;
f3nPlus1 ( n , count + 1);
} else {
n = n / 2;
f3nPlus1 ( n , count + 1);
}
}
}

Here's the immediate problem: When n != 1, what value does
f3nPlus1() return?
 
F

Flash Gordon

felipemartinsss said:
Hi Everybody.
I have a problem with the flag -O2 and I would like to know why this
problem is ocurring.
I have the following code:

temp = f3nPlus1( n, 0 );

You use the value returned by f3nPlus1

int f3nPlus1( int n, int count ) {
if( n == 1 ) {
return count + 1;

You return a value in this situation...


However, where is the returned value if you enter this else instead?
if(n % 2 != 0) {
n = 3 * n + 1;
f3nPlus1 ( n , count + 1);
} else {
n = n / 2;
f3nPlus1 ( n , count + 1);
}
}
}


When I compile the code with gcc -o f3nPlus1 f3nPlus1.c -lm -lcrypt -
pipe -ansi, everything's ok.
But, when I compile with gcc -O2 -o f3nPlus1 f3nPlus1.c -lm -lcrypt -
pipe -ansi, the execution give me wrong answers.

Try adding the following options "-ansi -pedantic -Wall -Wextra"
Read the man/info/other documentation for gcc to understand what they do.
 
J

James Kuyper

felipemartinsss wrote:
....
When I compile the code with gcc -o f3nPlus1 f3nPlus1.c -lm -lcrypt -
pipe -ansi, everything's ok.
But, when I compile with gcc -O2 -o f3nPlus1 f3nPlus1.c -lm -lcrypt -
pipe -ansi, the execution give me wrong answers.

It would make our task a lot easier if you would tell us

a) what you think the right answers should be.
b) what the wrong answers were that your program gave to you.
 
K

Keith Thompson

felipemartinsss said:
I have a problem with the flag -O2 and I would like to know why this
problem is ocurring.
I have the following code:

#include <stdio.h>
int f3nPlus1 (int n, int count); [snip]
temp = f3nPlus1( n, 0 );
/*printf ("temp: %d\n", temp);*/
if (temp > maximumCycle) {
maximumCycle = temp;
} [snip]
int f3nPlus1( int n, int count ) {
if( n == 1 ) {
return count + 1;
} else {
if(n % 2 != 0) {
n = 3 * n + 1;
f3nPlus1 ( n , count + 1);
} else {
n = n / 2;
f3nPlus1 ( n , count + 1);
}
}
}

When I compile the code with gcc -o f3nPlus1 f3nPlus1.c -lm -lcrypt -
pipe -ansi, everything's ok.
But, when I compile with gcc -O2 -o f3nPlus1 f3nPlus1.c -lm -lcrypt -
pipe -ansi, the execution give me wrong answers.

(The -lm, -lcrypt, and -pipe options are irrelevant.)

If a program behaves differently under different optimization options,
it's likely because the program exhibits undefined or unspecified
behavior.

In this case, there's one problem in your code that can easily be
detected by increasing the warning level. Compiling with
"gcc -c -ansi -pedantic -Wall -Wextra" gives me:

c.c: In function 'f3nPlus1':
c.c:55: warning: control reaches end of non-void function

You're not returning a value from f3nPlus1, but you're using the
value in main. Your recursive calls to f3nPlus1 just call it and
discard the result; you need to add a "return". (Speculation:
at -O0, it happens to return the value of the last expression
evaluated; at -O2, the code is rearranged so this doesn't happen.
But this kind of speculation isn't all that useful in most cases;
the it's easier to just fix the bug than to spend time analyzing
the symptoms.)

Turning on optimization causes the compiler to perform more analysis,
which can often let it detect more problems. Compiling with "gcc
-c -ansi -pedantic -Wall -Wextra -O3" gives me:

c.c: In function 'main':
c.c:19: warning: ignoring return value of 'fscanf', declared with attribute warn_unused_result
c.c: In function 'f3nPlus1':
c.c:55: warning: control reaches end of non-void function

You're calling fscanf() and ignoring its result. It can detect
input errors for you, but you're throwing away that information.
You should (almost) always check the result returned by any standard
function, at least when you're dealing with a file you've opened --
yes, even fclose().

Note that the details are specific to gcc, but the same general
approach is applicable to most compilers.

Some more things I noticed:

"while (!feof(filePtr))" is not the right way to write an input loop.
feof() becomes true *after* you've tried and failed to read beyond
the end of the file. I haven't tried running your program or
analyzing it in any great detail, but my guess is that your last
call to fscanf() at the end of the input will fail, but you'll go
ahead and use the values of begin and end anyway, values that are
probably left over from the previous call to fscanf. Recommended
reading: section 12 of the comp.lang.c FAQ, <http://www.c-faq.com/>;
question 12.2 seems particularly relevant. Furthermore, if there's
an input error, ferror() becomes true but feof() doesn't; in that
case, you'll probably have an infinite loop.

Style points: Please don't use tab characters in code posted to
Usenet. I've seen articles in which some news software somewhere
quietly eliminated all the leading tab characters, leaving all
the code unindented. And tab stops are typicall set to 8 columns;
personally, I find 8-column indentation to be too deep.

Several of the variables that you declare at the top of main()
could be declared inside the blocks that use them. For example,
begin, end, and temp could be declared inside the while loop.

It's likely that others will notice problems that I missed.
 
F

felipemartinsss

felipemartinsss said:
I have a problem with the flag -O2 and I would like to know why this
problem is ocurring.
I have the following code:
#include <stdio.h>
int f3nPlus1 (int n, int count); [snip]
temp = f3nPlus1( n, 0 );
/*printf ("temp: %d\n", temp);*/
if (temp > maximumCycle) {
maximumCycle = temp;
} [snip]
int f3nPlus1( int n, int count ) {
if( n == 1 ) {
return count + 1;
} else {
if(n % 2 != 0) {
n = 3 * n + 1;
f3nPlus1 ( n , count + 1);
} else {
n = n / 2;
f3nPlus1 ( n , count + 1);
}
}
}
When I compile the code with gcc -o f3nPlus1 f3nPlus1.c -lm -lcrypt -
pipe -ansi, everything's ok.
But, when I compile with gcc -O2 -o f3nPlus1 f3nPlus1.c -lm -lcrypt -
pipe -ansi, the execution give me wrong answers.

(The -lm, -lcrypt, and -pipe options are irrelevant.)

If a program behaves differently under different optimization options,
it's likely because the program exhibits undefined or unspecified
behavior.

In this case, there's one problem in your code that can easily be
detected by increasing the warning level. Compiling with
"gcc -c -ansi -pedantic -Wall -Wextra" gives me:

c.c: In function 'f3nPlus1':
c.c:55: warning: control reaches end of non-void function

You're not returning a value from f3nPlus1, but you're using the
value in main. Your recursive calls to f3nPlus1 just call it and
discard the result; you need to add a "return". (Speculation:
at -O0, it happens to return the value of the last expression
evaluated; at -O2, the code is rearranged so this doesn't happen.
But this kind of speculation isn't all that useful in most cases;
the it's easier to just fix the bug than to spend time analyzing
the symptoms.)

Turning on optimization causes the compiler to perform more analysis,
which can often let it detect more problems. Compiling with "gcc
-c -ansi -pedantic -Wall -Wextra -O3" gives me:

c.c: In function 'main':
c.c:19: warning: ignoring return value of 'fscanf', declared with attribute warn_unused_result
c.c: In function 'f3nPlus1':
c.c:55: warning: control reaches end of non-void function

You're calling fscanf() and ignoring its result. It can detect
input errors for you, but you're throwing away that information.
You should (almost) always check the result returned by any standard
function, at least when you're dealing with a file you've opened --
yes, even fclose().

Note that the details are specific to gcc, but the same general
approach is applicable to most compilers.

Some more things I noticed:

"while (!feof(filePtr))" is not the right way to write an input loop.
feof() becomes true *after* you've tried and failed to read beyond
the end of the file. I haven't tried running your program or
analyzing it in any great detail, but my guess is that your last
call to fscanf() at the end of the input will fail, but you'll go
ahead and use the values of begin and end anyway, values that are
probably left over from the previous call to fscanf. Recommended
reading: section 12 of the comp.lang.c FAQ, <http://www.c-faq.com/>;
question 12.2 seems particularly relevant. Furthermore, if there's
an input error, ferror() becomes true but feof() doesn't; in that
case, you'll probably have an infinite loop.

Style points: Please don't use tab characters in code posted to
Usenet. I've seen articles in which some news software somewhere
quietly eliminated all the leading tab characters, leaving all
the code unindented. And tab stops are typicall set to 8 columns;
personally, I find 8-column indentation to be too deep.

Several of the variables that you declare at the top of main()
could be declared inside the blocks that use them. For example,
begin, end, and temp could be declared inside the while loop.

It's likely that others will notice problems that I missed.

--
Keith Thompson (The_Other_Keith) (e-mail address removed) <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Hi,
thanks for all! =]
 
C

CBFalconer

felipemartinsss said:
I have a problem with the flag -O2 and I would like to know why
this problem is ocurring. I have the following code:
.... snip ...

if (filePtr) {
while (!feof(filePtr)) {
fscanf(filePtr, "%d%d\n", &begin, &end);

feof is not a suitable mechanism. It only is set after an input
routine has failed because of EOF.
 
F

felipemartinsss

felipemartinsss said:
Hi Everybody.
I have a problem with the flag -O2 and I would like to know why this
problem is ocurring.
I have the following code:
[...]
while (!feof(filePtr)) {

This is not the problem you asked about, but it is
another error you will eventually need to fix. Please
see Question 12.2 in the comp.lang.c Frequently Asked
Questions (FAQ) list at said:
[...]
int f3nPlus1( int n, int count ) {
if( n == 1 ) {
return count + 1;
} else {
if(n % 2 != 0) {
n = 3 * n + 1;
f3nPlus1 ( n , count + 1);
} else {
n = n / 2;
f3nPlus1 ( n , count + 1);
}
}
}

Here's the immediate problem: When n != 1, what value does
f3nPlus1() return?

Yes. It was not working very well, so I couldn't continue. But I was
not receiving the warnings, with the option -Wall I changed
the code and solved the problem.
Thanks for All again.
 

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

Similar Threads

Fibonacci 0
Bug in gcc? 5
Adding adressing of IPv6 to program 1
Why struct not globally changed in function? 1
Queue in C 25
Help in this program. 2
Bug in GCC? 10
Lexical Analysis on C++ 1

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top