【问题标题】:what would cause gcc -O2 to not work when -O0 is good?当 -O0 很好时,什么会导致 gcc -O2 不起作用?
【发布时间】:2023-03-17 15:12:01
【问题描述】:

我有一些 C 代码,经过艰苦的努力,在 Excel 中手动执行操作后,我验证了我通过 gcc -O0 编译的可执行文件运行正确,但如果我使用 -O2 编译,我的输出很糟糕。

什么可能导致这种情况? 到目前为止,我已经将问题追踪到它读取数据的位置, 这是它读取的输入文件的总集合,我读取的每一行数据(来自文本文件的数字)我立即打印到标准输出并重定向到一个名为 O0.txt 或 O2.txt 的文件中。如果我比较这些文件,我会发现在我期望看到完全相同的数字时存在显着差异。

这是 gcc-4.3.4 suse linux

这里有一个 sn-p 代码,用于显示什么不适用于 -O2 但它确实适用于 -O0 基于 printf 并将输出重定向到 O0.txtO2.txt

# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <ctype.h>

# define ZZ 8192

double x[9000];
double y[9000];

double z[2][17][20][3600];

void Read_Data ( FILE *fp, const int R, const int S, const int T, const int type, const int M )
{
   char line[ZZ];
   int count;
   double a, b, c, d, e, f, g, h;

   for ( r = 0; r < 12; r++ )   /* skip past header */
      fgets( line, LS, fp );

   for ( r = 0; r < R; r++ )
   {
      for ( s = 0; s < S; s++ )
      {
         for ( t = 0; t < T; t++ )
         {
            sscanf( line, "%d %lf %lf %lf   %lf %lf   %lf %lf   %lf %lf    %lf %lf", &a, &b, &c, &d, &e, &f, &g, &h );

            if (( a == 0 ) && ( b == 0 ))
               x[t] = 1e-9;
            else
               x[t] = a*a + b*b;

            if (( g == 0 ) && ( h == 0 ))
               y[t] = 1e-9;
            else
               y[t] = g*g + h*h;

printf("%18.12e  %18.12e      %18.12e  %18.12e\n", a, b, c, d );

            fgets( line, ZZ, fp );
         }

         if ( type == 1 )
         {
            z[0][M][r][s] = Find_Median( x, T );
            z[1][M][r][s] = Find_Median( y, T );
         }
         else if ( type == 2 )
         {
            sum_x = 0;   sumy = 0;
            for ( tt = 0; tt < T; tt+ )
            {
               sumx += x[tt];
               sumy += y[tt];
            }
            z[0][M][r][s] = sumx / ((double)T);
            z[1][M][r][s] = sumy / ((double)T);
         }
      }
   }
}

int main ( int argc, char *argv[] )
{
   FILE *fpi;

   Parse_Command_line( argc, argv );

/* other code here */

   T has value of 10
   S has value of 10
   R has value of 180

/* other code here */

   fpi = fopen("mydata", "r" );

   for ( m = 0; m < 17; m++ )
   {
      Read_Data( fpi, R, S, T, m);
   }

/* other code here */

   return 0;
}

【问题讨论】:

  • for ( r = 0; r &lt; 12; r++ ) r 定义在哪里?
  • sscanf( line, "%d %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf", &amp;a, &amp;b, &amp;c, &amp;d, &amp;e, &amp;f, &amp;g, &amp;h ); 你使用了%dadouble
  • 相信我r是定义的,这是一个sn-p的代码。仅使用了 -O2 -lm -Wall 的编译标志,并且有 zero 警告。因为我必须混淆代码并更改变量名称才能将其发布在这里,所以上面的文本中肯定会有一些小错误,例如scanf
  • 我已确认 SLES 11.4 x86_64 中的系统编译器 -O2 和 gcc-4.3-4 存在问题,但在使用 gcc 4.8 的 SLES 12.3 中不会出现问题.5.这会被认为是编译器问题还是错误?

标签: gcc optimization


【解决方案1】:

我在读取例程中发现错误,不是编译器问题。

尽管由于某种原因,在 gcc-4.8.5 上使用 -O2 或我以后可用的任何东西编译时问题并未表现出来。

上面的代码sn-p竟然被改正了,一定是有眼界的, 原源代码中的问题是

/* here was the problem in original code */
for ( r = 0; r < r; r++ )   /* skip past header */
   fgets( line, LS, fp );

没有使用带有-O2 选项的gcc_4.3.4 跳过过去的标头,但可以使用-O0-O1

-O2- did allow the program to read in all the data from the file correctly
and the program ran correctly when compiling with

gcc-4.8  {sles 11.4 installed by novell update}
gcc-5 {sles 11.4 installed by novell update}
gcc-4.8.5 {native in sles 12.3}

gcc 7.x as of 2018-02-20 manually built from source

我得到了在使用gcc_4.3.4-O2 编译的sles 11.4 中运行的原始代码

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-15
    • 2020-06-27
    • 1970-01-01
    • 1970-01-01
    • 2016-12-26
    • 1970-01-01
    相关资源
    最近更新 更多