Блог пользователя yeputons

Автор yeputons, 14 лет назад, По-русски
Собственно, сабж c контеста:
http://pastebin.com/jvkUcZx3
Казалось бы, процедура, вызываемая от параметров, равных побайтно, должна возвращать один и тот же результат. Ан нет - они различаются.
В MSVC++ всё ок.

Предложили еще один вариант. Он гораздо проще и даже, казалось бы, понятно, почему случается. По стандарту - результат неопределён.

COLLECT_GCC=C:\Soft\MinGW\bin\gcc.EXE
COLLECT_LTO_WRAPPER=c:/soft/mingw/bin/../libexec/gcc/mingw32/4.5.0/lto-wrapper.exe
Target: mingw32
Configured with: ../gcc-4.5.0/configure --enable-languages=c,c++,ada,fortran,objc,obj-c++ --disable-sjlj-exceptions --with-dwarf2 --enable-shared --enable-libgomp --disable-win32-registry --enable-libstdcxx-debug --enable-version-specific-runtime-libs --disable-werror --build=mingw32 --prefix=/mingw
Thread model: win32
gcc version 4.5.0 (GCC)

Intel Core i3 M350 (x86)

UPD. На сервере CF тоже выдает некорректный результат. Попробуйте во вкладке "запуск".
UPD2. В одном из комментариев выдвинули дополнительное требование: включите оптимизатор (-O1/-O2)
UPD3. Две абсолютно одинаковые посылки под разными компиляторами получают разные вердикты: GCC - WA14 (240112), MSVC++ - OK (240115). Задача B из CF49
  • Проголосовать: нравится
  • +43
  • Проголосовать: не нравится

14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Вот результат на моей машине. Результат равен. 

Хоть бы версию указал GCC бы, под которой тестил. :)
14 лет назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

У меня тоже GCC версии 4.5.0. 32-бита, Windows 7. Программа корректно работает.

g++.exe -O2 -Wall -Wl,--stack=64000000,--enable-auto-import -o ! !.! 

14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
20971519 == 20971520

Win7 + GCC 3.4.2 (mingw-special)
14 лет назад, # |
Rev. 3   Проголосовать: нравится +5 Проголосовать: не нравится
В результате экспериментов, я понял, что у меня зависимость такая:

Если использовать ключ -O2, то результат неверный.
Если не использовать, то результат верный.

Видать, это баги оптимизатора. На сервере, насколько я помню, стоит достаточно старая версия, и есть ключ -O2, вот и результат. Разумеется, это баги компилятора.

UPD:
на сервере стоит
GNU C++ 4
g++.exe -DONLINE_JUDGE -fno-asm -lm -s -x c++ -Wl,--stack=268435456 -O2 -o %name%.exe %1
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Аналогично.
    Но, что интересно, -O1 также убивает корректность.
14 лет назад, # |
Rev. 2   Проголосовать: нравится +5 Проголосовать: не нравится
Линуксовый gcc нормально себя ведет. Версия 4.4.4. Что с "-O2", что без него.
(Правка: 64-битная версия, 32-битную не проверял)
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
On Ubuntu 10.10 x86_64, which uses gcc 4.4, I get "20971520 == 20971520" as output, no matter which level of optimization I use, so either the bug has been introduced in 4.5 or it occurs only on Windows MINGW.
I also experienced the bug at CF#49-B, but I was lucky that it already failed during the pretest.
14 лет назад, # |
  Проголосовать: нравится +5 Проголосовать: не нравится
Вот проще пример. Не работает с g++ 4.5 -O2

#include <cstring>
#include <cstdio>

int f(int x) { return 1 << x; }

int main() {
for (int i = 0, j = 42; i < 1000000; ++i)
if (!memcmp(&i, &j, sizeof(int))) 
printf("%d == %d\n", f(i), f(j));
return 0;
}

В данном примере f(j) вычисляется на этапе компиляции(оптимизации), f(i) как и memcmp(&i, &j, sizeof(int)) - во время выполнения. Оптимизатор думает что 1 << 42 = 0, а процессор думает что 1 << 42 = 1024.
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Windows only. На линуксе "1024 == 1024". gcc 4.4.4, 64-bit.
  • 14 лет назад, # ^ |
      Проголосовать: нравится +5 Проголосовать: не нравится
    Этот пример уж точно в рамках стандарта :)

    5.8 1 The behavior is undefined if the right operand is negative, or
    greater than or equal to the length in bits of the promoted left operand.
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Возможно вы правы, тогда у меня есть ещё один пример

      int f(int x) { 
      return (int)(x * 0.33333333333333333333333);
      }
      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Мне кажется, дело может быть в том, что в некоторых режимах компилятора промежуточные результаты вычислений не приводятся к double, а остаются во внутреннем (более точном) представлении.
        Можно посмотреть соответствующие настройки.
        • 14 лет назад, # ^ |
            Проголосовать: нравится +5 Проголосовать: не нравится
          Либо же действительно в режиме с оптимизациями выражений подобное поведение (что является ошибкой в компиляторе) - слишком высокая точность вычислений.
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
На Windows также "1024 == 1024" если компилировть 64-битным gcc (или старым версии 3.4.1)
14 лет назад, # |
Rev. 2   Проголосовать: нравится +5 Проголосовать: не нравится
When I compile it with "g++ -m32 -O2 gccbugtest.cpp" I indeed get the wrong result. It seems that only 32-bit code generation is bugged, but it's bugged on Linux too.
edit: The second test gives "1024 == 1024" even with 32-bit.
14 лет назад, # |
  Проголосовать: нравится +5 Проголосовать: не нравится
-ffloat-store compiler flag solves the floating-point problem for me. The other one I don't have.

Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.4.3-4ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --program-suffix=-4.4 --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-plugin --enable-objc-gc --enable-targets=all --disable-werror --with-arch-32=i486 --with-tune=generic --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
Thread model: posix
gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5)
14 лет назад, # |
  Проголосовать: нравится +10 Проголосовать: не нравится
Just to clarify: these are not bugs. 1<<42 is undefined behaviour, and the other one is also well-known.