1. C++ / Говнокод #9686

    +999

    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
    6. 6
    7. 7
    8. 8
    9. 9
    assert(t1.tm_sec == t2.tm_sec);
            assert(t1.tm_min == t2.tm_min);
            assert(t1.tm_hour == t2.tm_hour);
            assert(t1.tm_mday == t2.tm_mday);
            assert(t1.tm_mon == t2.tm_mon);
            assert(t1.tm_year == t2.tm_year);
            assert(t1.tm_wday == t2.tm_wday);
            assert(t1.tm_yday == t2.tm_yday);
            assert(t1.tm_isdst == t2.tm_isdst);

    фрагмент из кода библиотеки SOCI: http://soci.sourceforge.net/

    наконец-то исправили на: assert(memcmp(&t1, &t2, sizeof(std::tm)) == 0);

    Запостил: niXman, 15 Марта 2012

    Комментарии (27) RSS

    • Чего? 'memcmp' в общем случае будет как раз таки говнокодом. В оригинальном варианте было сделано правильно (а кому сейчас легко?).
      Ответить
      • поясни..
        Ответить
        • Потому что у структур могут быть поля, которые действительно влияют на их значения, а могут быть служебные поля, например ID, которые могут быть не равны даже для эквивалентных объектов.
          А ещё могут быть указатели на одинаковые объекты, но указатели разные.
          А ещё memmcmp это кулхацкерство.
          Ответить
          • >у структур
            тут речь идет об единственном типе структуры.
            а так да, спасибо за экспланацию.
            Ответить
            • А это вы тот самый человек, которого на говнокоде в каком то треде называли Петей и который является невероятным гением и ворочает шаблонами С++ направо и налево, что аж далеко не все поймут? Так круто ворочает, что аж все девушки визжат при одном только вашем упоминании?

              Не могу найти где это было...
              Ответить
        • Ну, вообще говоря, в общем случае любая структура состоит как из значимой пямяти (т.е. собственно полей данных) , так и из байтов-заполнителей, т.е. не используемой для представления данных пямяти, вставленной в структуру только для достижения правильного выравнивания полей. По-английски это называется padding bytes. (Эта, в частности, та причина, по которой в общем случае размер всей структуры не равен сумме размеров ее полей.)

          Padding bytes могут присутствовать между полями структуры или в ее конце. Значения этих байтов-заполнителей - непредсказуемы, т.е. они содержат всякий мусор. Когда ты сравниваешь два объекта через 'memcmp', то волей-неволей сравниваешь и эти мусорные байты. Запросто может получиться, что настоящие содержательные поля в двух объектах совпадают, а вот промежуточные байты- заполнители - различаются. В такой ситуации 'memcmp' скажет тебе, что объекты не равны. А они таки равны.

          Понятно, что в данно конкретном случае байтов-заполнителей, скорее всего, нет. Но это тем не мнее не повод пользовать 'memcmp' для выполнения такого сравнения.
          Ответить
          • Это ассерт и дебаг-рантайм гарантирует нам что заполнены они будут филлером: 0xcc.
            Ответить
            • Это не по стандарту С++, а реализацией конкретного компилятора. Писать библиотеку, рассчитанную на конкретный компилятор по меньшей мере глупо... Почему, обычно именно гости или виртуалы предлагают всякие глупости?
              Ответить
          • Реальна ли ситуация, при которой один и тот же компилятор под одну и ту же платформу сделает разный паддинг для одной и той же структуры? Где-то 0xCC, где-то 0xBB?
            Ответить
            • Вполне. В релизной сборке там просто мусор.

              З.Ы. Ну с другой стороны там и ассерта нету.
              Ответить
              • а, ну то есть их просто никто специально не заполняет, и стало быть там будет что Боженька захочет?

                Тогда memcmp просто не нужен тут
                Ответить
                • В отладочной вроде заполняет. Но опять же смотря какой конпелятор.
                  Ответить
                  • в отладночной понятно. Это еще Макконел писал, что всегда заполняйте неиспользуемую область и свежеочищенную область каким-нить 0xDEADBEAF чтобы удобнее было дампы читать
                    Ответить
                    • > читать

                      Чтобы дампы чаще и быстрее получались, лол. На самом деле самый главный профит от заполнения.
                      Ответить
                      • тогда нужно всё заполнять 0x00, а весь неиспользуемый код 0xCC, не?
                        Ответить
                        • Цц для данных тоже норм. Быстрее крашится если поюзать как число или указатель.

                          А вот нули плохой паттерн.
                          Ответить
                          • почему, ведь ноль тоже покрашется?
                            хотя и CC наверное тоже: "случайно" попасть в настоящие данные из такого маленького адрса нельзя, там вроде самый низ адресного пространства обычно специально никуда не мапица?

                            Или он плохой тем, что его нельзя отличить от от умышленных нулей, пустых строк итд?
                            Ответить
                            • Да, на нули часто проверяют.
                              Ответить
                              • https://www.codeguru.com/cpp/w-p/win32/tutorials/article.php/c9535/Inside-CRT-Debug-Heap-Management.htm

                                во даже как)
                                Ответить
      • начнем с того, что нигде не сказано, что t1 и t2 -- инстансы одной и той же структуры:)
        Ответить
    • Если структура - POD, то можно просто:
      assert( t1==t2 );
      а если нет - то с memcmp играться не стоит.
      Ответить
      • нет, нельзя

        не сравниваются так структуры, к сожалению. В сишечке. В C# вроде бы можно
        Ответить
    • показать все, что скрытоvanished
      Ответить

    Добавить комментарий