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

Автор yarrr, 13 лет назад, По-русски

Всем привет,

Сегодня при дорешивании Харьковской Зимней Школы (а у них стоит G++ 4.5.3) столкнулся с такой проблемой, что довольно очевидное дерево отрезков получало WA2, когда как у меня часовой стресс-тест никаких багов не нашёл. Задача такая: дан массив, поступают запросы "GET l r a b", нужно выводить количество чисел на [l,r], значения которых находятся в промежутке [a,b].

Мой код: http://pastie.org/3810241 Наивное решение: http://pastie.org/3810252 Тест: http://pastie.org/3810319 Скрин: http://imgur.com/tquWU

После часа шаманства нашёл причину, если код функции calc просто перенести в query, или же тупо написать inline перед calc, то всё становится окей.

Причём у меня на GCC 4.6.x разницы никакой нет, а на 4.5 ветке ответы получаются разными. Компилирую с "-O2".

Я не особо знаток плюсов, помогите пожалуйста, почему так получается?

  • Проголосовать: нравится
  • +6
  • Проголосовать: не нравится

»
13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

На ideone.com с GCC 4.3.4 тоже самое: http://ideone.com/9XbOr

»
13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

а пробовали свой бинпоиск писать?

  • »
    »
    13 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

    Я пробовал за линию проходить. Всё равно та же тема: http://ideone.com/mj3im

    Но там тоже прикол есть. Если линию переписать на итераторы, то становится правильно: http://ideone.com/fEOY4

    Просто я столкнулся с проблемой, когда уже убрал все векторы (там обновлять значения просто нужно), написал декартово дерево и там та же проблема. Если функцию подсчёта значений в дереве заинлайнить, то всё ок: http://ideone.com/2WxDs , без инлайна: http://ideone.com/WzkyZ

»
13 лет назад, # |
  Проголосовать: нравится +4 Проголосовать: не нравится

Там налицо какой-то баг оптимизатора. Например добавление

cerr <<"!!!"<<v<<" "<<l <<" "<<r<<" "<<tl<<" "<<tr<<" "<<a<<" "<<b<< " -> "<<res<<endl; в функцию calc приводит к адекватной работе. Сейчас попробую точно разобраться что происходит.

  • »
    »
    13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Я думаю оптимизаторы набажили с регистрами, забыв обнулить регистр или поюзав один регистр для разных переменных. Надо послать разработчикам и забить. Но если вы хотите поизучать машинный код, ваше право, мьсе.

    • »
      »
      »
      13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Ну глубже ассемблера лезть точно глупо, а знания его, чтобы разобраться что происходит мне не хватит.А отправлять разработчикам почти бессмысленно — на более новых версиях не проявляется. Уже отрепортили видимо.

»
13 лет назад, # |
Rev. 2   Проголосовать: нравится +9 Проголосовать: не нравится

Сильно уменьшенная версия кода.

А теперь магия! Вот тут баг не проявляется. Оптимизатор демон. как он это делает?

UPD: Видимо с нулем баг не компилятора, а мой. Там просто ответ правильный меняется. Так де по просьбам трудящихся лучше отформатированный и еще уменьшенный код.

  • »
    »
    13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Я не вижу разницы в коде, только разницу в стиле расцветки, сделай одинаковую пожалуйста, иначе полный бред.

    • »
      »
      »
      13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      там в одном res = 0, в другом res = 1. Но да, Паша, сделай одну расцветку и форматирование :)

    • »
      »
      »
      13 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Это случайно. Сейчас пофикшу. Разница в том, что в одном случае res = 1 в другом res = 0

      • »
        »
        »
        »
        13 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        Ага, я уже увидел, когда скопировал оба куска кода в блокнот.

  • »
    »
    13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    В 4.4 и 4.6 не проявляется.

»
13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Я не знаю, как они умудрились, но в asm-коде тупо нету присваивания res = ..., в него сразу кладется результат вычисления calc(). Это видно при сравнении кода в gcc4.6 и в gcc4.5