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

    +116

    1. 1
    2. 2
    3. 3
    short lPort = atoi(szTemp);
    if (lPort <= 0 || lPort > 65535)
    	lPort = 80;

    Запостил: absolut, 10 Мая 2012

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

    • Правильно, зачем вводить порты больше 32767 ? )
      Ответить
    • Как обычно, говонокодовость заключается в первой строчке: в самом факте использовании функции 'atoi', а также в бездумном запихивании int-овго результата в переменную типа 'short'.

      Все остальное - малозначительные детали.
      Ответить
      • atoi чем не угодил то?
        Ответить
        • Видимо тем, что парсит всякую ересь в духе 115dhdhd.
          Ответить
          • Ну это воообще-то единый стандарт для всех функция конвертации в стандартной библиотеке: допустимая входная строка имеет вид '[пробелы]<число>[всякий мусор]'. Но если хочется отлавливать ситуации со "всяким мусором" в конце, то, конечно, функции группы 'strto...' подходят хорошо.

            По моему мнению, основная проблема с 'atoi' не в этом, а в том, что функция порождает неопределенное поведение при переполнении и тупо возвращает '0' при некорректном формате входа.
            Ответить
            • Тупо возвращение 0 не так уж и ужасно - например для выдачи сообщения "Порт должен быть целым числом в диапазоне от 1 до 65535" этого вполне достаточно. А вот неопределенное поведение при переполнении и игнор мусора в конце - это да, проблема.
              Ответить
        • Функции группы 'ato...' не дают никакого способа отлова ошибок при конвертации. Некорректный вход приводит к возврату '0'. И разбирайся потом, был ли там на входе именно '0', или произошла ошибка. Но это еще полбеды. Вторая проблема - при переполнении они вызывают неопределенное поведение. От этого никакой защиты нет.

          Это часто умиляет в пионэрском говнкоде, когда пионэр осознает наличие проблемы, и для ее "решения" воздвигает вокруг вызова 'atoi' горы дополнительного кода, призванного проверять как коректность формата, так и непереполняемость результата. При этом сложность этого нагромождения кода обычно на порядки превышает сложность самого 'atoi' и, как правило, содержит внутри себя еще одну неявную реализацию 'atoi' вручную :)

          На самом деле функции группы 'ato...' никакой практической ценности не представляют. Другой способ конвертации строк в число - функция 'sscanf' - несколько лучше, но тоже вывзвает неопределенное поведение при переполнении.

          Единственно правильный способ перевода строки в число - это функции группы 'strto...'. Пользуйтесь 'strtol' и забудьте навсегда про существование 'atoi'. Функции группы 'strto...' для того и были введены, чтобы люди перестали мучать этот несчастный 'atoi'.

          P.S. В коде "продвинутых" пионэров встречается даже варианты, когда присле вызова 'atoi' и получения нуля в ответ делается вызов 'strtol', чтобы выяснить, что случилось :)
          Ответить
    • "Из исходников windows firewall" - как-то само напрашивается :-)
      Ответить
    • glibc 2.14
      /* Convert a string to an int.  */
      int
      atoi (const char *nptr)
      {
        return (int) strtol (nptr, (char **) NULL, 10);
      }
      Ответить

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