1. Си / Говнокод #10058

    +138

    1. 1
    memset(cb->chars, cb->width * cb->height, ' ');

    Мой однострочный эпик фейл.

    Запостил: bormand, 27 Апреля 2012

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

    • а что такое cb?
      Ответить
      • character buffer
        struct CharBuffer {
            unsigned int width;
            unsigned int height;
            char *chars;
        };
        Ответить
    • Не аллоцирован указатель chars? Другого говна не вижу.
      Ответить
      • Нет, говно именно в этой строке.
        Ответить
      • аргументы перепутаны местами
        Ответить
        • Ага. Был бы второй аргумент хотя бы char а не int, компилятор сразу выдал бы предупреждение.
          Ответить
        • И няшаблядский кокомпилятор даже ничего не заподозрил, приводя целое к указателю!
          Ответить
          • Где? Перепутали то int и size_t который тоже int.
            Ответить
            • Ой, поправочка:
              И няшаблядский кокомпилятор даже ничего не заподозрил, приводя 4байтовое целое к байту!
              Ответить
              • где ты байт-то нашёл?
                Ответить
              • void *memset(void *s, int c, size_t n);
                Где тут байт?
                Ответить
                • показать все, что скрытоА почему int c, он заполняет по байту же, а не по 4 байта?

                  Короче, криворукая няшаблядская библиотека. Кстати, библиотеку можно считать частью компилятора? Ну, чтобы слово "кокомпилятор" было куда ввернуть.
                  Ответить
                  • В стандартной библиотеке языке С по историческим причнам не бывает параметров типа 'char', 'short', 'float' и т.п. Минимальными типами параметров является 'int' и 'double'. Происходит это потому, что на заре языка С не требовалось предварительного объявления функций с указанием прототипа. Функции можно было вызывать без знания прототипа, что заставляло компилятор "угадывать" фактические типы параметров по типам передаваемых аргументов (и предпологать, что тип возврата - 'int'). При передаче целочисленного аргумента типа 'char', 'short' или 'int' автоматически подразумевалось, что соответствующий параметр имеет тип 'int'. Поэтому в определениях библиотечных функций всегда используются именно те типы параметров, которые "угадает" компилятор при вызове необъявленной функции.

                    Возможность вызова функций без предварительного объявления была исключена в стандарте С99. Но даже стандарт С99 не требует наличия прототипа для вызова функции. Например, для С99 достаточно такого объявления 'memset'
                    void *memset();

                    и функцую уже можно вызывать. При этом компилятор опять же будет "угадывать" типа параметров как описано выше.
                    Ответить
                    • Это первый вывод типов и количества параметров, посоны.
                      Функциональные языки оказались не первыми. А вывод количества параметров функции - функциональные языки до сих пор не осилили.
                      Ответить
          • перепутаны второй и третий аргумент, а не первый и второй.
            Ответить
        • показать все, что скрытоа если бы вы проверяли свой код PVS-Studio то она бы сразу выдала один из двух warning'ов

          V512 A call of the 'memset' function will lead to underflow of the buffer 'chars'
          V512 A call of the 'memset' function will lead to overflow of the buffer 'chars'

          и вообще это супер анализатор по выявлению ошибок при переносе на x64 или с линуксячьего
          LP64 на вендовый LLP64
          Ответить
    • фейл с порядком аргументов?
      Ответить
    • Это C, детка.

      Какая-нибудь Java просто не дала бы преобразовать int в byte без явного каста.
      Ответить
      • Где тут байт? В прототипе int.
        Ответить
        • А это к вопросу о кривизне рук авторов стандартной библиотеки - почему у них байт для заполнения массива передаётся как int.
          Ответить
          • А с этим полностью согласен, о чем и писалось выше.

            http://govnokod.ru/10058#comment136594
            Ответить
          • http://goo.gl/k8rnq
            Ответить
            • То есть это сделано для совместимости с криворукими макаками, которые не подключают инклюдники, в которых описан прототип функции, потому что для неизвестных типов Си выбирает int? Мало того, что Си позволяет использовать неописанные функции, так ещё и библиотеки под криворукость подстроены.
              Ответить
      • ага, а Reader.read() возвращает int, хотя сам класс читает _символьные_ потоки
        Ответить
        • Это чтобы можно было вернуть -1.
          Ответить
          • аналогично можно было бы возвращать \0
            Ответить
            • \0 может быть вполне валидным символом, действительно прочитанным из потока.
              Ответить
              • (char)-1?
                Ответить
                • Не помню где видел, но в каком-то языке при чтении чаровского значения был таки отдельный символ за пределами чара для признака конца файла. Соответственно, в потоке данных этот символ попасться не мог и проблема не существовала. Но подробности вылетели из головы.
                  Ответить

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