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

    +135

    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
    6. 6
    char* getID(){
      uint32_t id = calcuate_id(); // Непринципиально, сложные какие то вычисления
      static char str[16] = {0};
      sprintf(str, "%ud", id);
      return str;
    }

    На самом деле кусок модуля к nginx. Вычисляетися целое число, преобразуется в десятичное представление....

    Запостил: klavdiev, 29 Августа 2013

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

    • Разве безопасно возвращать указатели на локальные переменные? О_о
      Ответить
      • э.... на ЛОКАЛЬНЫЕ опасно )
        Ответить
      • А это и не локальная переменная ;)

        А вообще этот код не потокобезопасен. Да и в одном потоке могут возникнуть проблемы, если не задокументирован тот факт, что результат живет только до следующего вызова.
        Ответить
        • > если не задокументирован
          Хотя тогда результат могут и освободить с помощью free...
          Ответить
          • В сишечках есть множество способов.
            И указатель или нет - разница невелика.
            Ответить
            • > разница невелика
              Их отделяет всего один символ: & или *.
              Ответить
        • Да и функцию неплохо бы задекларировать как возвращающую указатель на константную строку - на всякий случай, от дурака.
          Ответить
        • Что-то я сомневаюсь, что nginx треды использует.
          Ответить
      • Использование указателя на объект, сконструированный на автоматической памяти, после выхода этого объекта из объемлющей области видимости - UB. Со статическими объектами это UB только в случае многопоточного доступа.
        Ответить
        • Но в данном случае мы видим не автоматический объект, а обычный статик :)

          И аналогичной херни в той же libc полно...
          Ответить
        • P.S. А ну вот, пока я комментировал, Роман уже пофиксил коммент на "Со статическими объектами это UB только в случае многопоточного доступа" ;)
          Ответить
          • в ковнокодике 5.0 будет версионирование комментов и оповещения на websocket
            Ответить
    • Может косяк в %ud (который сам по себе бессмысленен, если мы не хотим получить d на конце), вместо которого надо использовать PRIu32?
      Ответить
    • Косяк в том, что статическая переменная инициализируется единожды. И если в первый вызов получим число 12345 и строку "12345", то во второй вызов с результатом 3 мы получим строку "32345".
      Остальное по поводу free и нежелательной многопоточности вполне документировано, я же написал, это кусок модуля для nginx
      Ответить
      • > 3 мы получим строку "32345"
        Проверяли? :) Вот лишнее d оно пишет, да. Но откуда там возьмется 2345?! printf же сам всегда терминирует строку нулем. Или в api nginx'овых модулей не нультерминейтед строки, и для него важен этот хлам после нолика?
        Ответить
        • проверяли, естественно.
          Ответить
          • Ну т.е. согласно API nginx'а этот getID должен возвращать не null-terminated строку, а строку дополненную до 16 символов нулями?
            Ответить

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