Когда программа, как показано ниже, запускается, она выдает нормально:
j= 0 9007199616606190.000000 = x
k= 0 9007199616606190.000000 = [x]
r= 31443101 0.000000 = m*(x-[x])
Но когда закомментированная строка ( т.е. //if (argc>1) r = atol(argv[1]);
) не закомментирована, она выдает:
j= 20000 9007199616606190.000000 = x
k= 17285 9007199616606190.000000 = [x]
r= 31443101 0.000000 = m*(x-[x])
, хотя эта строка не должна иметь никакого эффекта, поскольку argc>1
имеет значение false.Кто-нибудь получил правдоподобное объяснение этой проблемы?Воспроизводится ли он на любых других системах?
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(int argc, char *argv[]) {
int j, k, m=10000;
double r=31443101, jroot=sqrt(83), x;
//if (argc>1) r = atol(argv[1]);
x = r * r * jroot;
j = m*(x-floor(x));
k = floor(m*(x-floor(x)));
printf ("j= %9d %24.6f = x\n", j, x);
printf ("k= %9d %24.6f = [x]\n", k, floor(x));
printf ("r= %9.0f %24.6f = m*(x-[x]) \n", r, m*(x-floor(x)));
return 0;
}
Обратите внимание, тестовая система = система AMD Athlon 64 5200+ с Linux 2.6.35.14-96.fc14.i686 ( т.е. , загружено дозапустить 32-битную ОС на 64-битном HW) с gcc (GCC) 4.5.1 20100924 (Red Hat 4.5.1-4)
Обновление - Несколько часов назад яопубликовал комментарий о том, что код, сгенерированный с оператором if
и без него, отличается только смещениями стека и некоторым пропущенным кодом.Теперь я нахожу, что этот комментарий был не совсем правильным; то есть это верно для неоптимизированного кода, но не верно для кода -O3, который я выполнил.
Влияние переключателя оптимизации на проблему:
- -O0: обе версии программы работают нормально
- -O2 или -O3: в версии с комментарием есть ошибка, как указано выше, где
j=20000
и k=17285
- -O1:Версия с комментариями имеет
j=20000
(ошибка) и k=0
(ОК)
В любом случае, если посмотреть на списки кодов -O3 -S, два случая отличаются в основном пропущенным кодом if
истек смещается до строки, предшествующей call floor
, и в этот момент код с-if имеет на fstpl
больше, чем код без-if:
... ;; code without comment:
fmul %st, %st(1)
fxch %st(1)
fstpl (%esp)
fxch %st(1)
fstpl 48(%esp)
fstpl 32(%esp)
call floor
movl $.LC2, (%esp)
fnstcw 86(%esp)
movzwl 86(%esp), %eax
...
... ;; versus code with comment:
fmul %st, %st(1)
fxch %st(1)
fstpl (%esp)
fxch %st(1)
fstpl 48(%esp)
fstpl 32(%esp)
fstpl 64(%esp)
call floor
movl $.LC3, (%esp)
fnstcw 102(%esp)
movzwl 102(%esp), %eax
...
Я не выяснил причинуразница.