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

    +136

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    char *stringFromDTM(MDTM *dtm)
    {
        if (dtm->count < 1)
        return "";
        uint32_t size = (sizeof(MDTMPoint) + sizeof(uint32_t)) * dtm->count;
        void *data = calloc(1, size);
        uint32_t *ptr = data;
        *(ptr++) = size;
        uint32_t index;
        for (index = 0; index < dtm->count; index++)
        *(ptr++) = dtm->points[index].x;
        for (index = 0; index < dtm->count; index++)
        *(ptr++) = dtm->points[index].y;
        for (index = 0; index < dtm->count; index++)
        *(ptr++) = dtm->points[index].color;
        for (index = 0; index < dtm->count; index++)
        *(ptr++) = dtm->points[index].tol;
        for (index = 0; index < dtm->count; index++)
        *(ptr++) = dtm->points[index].size;
        for (index = 0; index < dtm->count; index++)
        *(ptr++) = dtm->points[index].x;
        bool *bptr = (bool *)ptr;
        for (index = 0; index < dtm->count; index++)
        *(bptr++) = dtm->points[index].bad;
        uint32_t len = compressBound(size);
        char *buffer = malloc(len);
        if (compress((Bytef *)buffer, (uLongf *)&len, data, size) == Z_OK)
        {
            free(data);
            char *compressed = malloc(len + sizeof(uint32_t));
            *((uint32_t *)(compressed)) = len;
            strcpy(compressed + sizeof(uint32_t), buffer);
            free(buffer);
        }
        free(buffer);
        free(data);
        return "";
    }

    Я так и не раскурил, почему так, а не иначе.

    Запостил: Cynicrus, 01 Декабря 2014

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

    • Строки 5-6. Всегда прикалывало. Интерфейсом calloc(num, size) никто не пользуется.

      Пару раз в качестве стилевого эксперимента пытался передавать calloc() оба параметра без предварительного умножения, но как-то не прижилось.

      PS strcpy() на потенциально двоичные данные? выглядит загадочно. (и да, данные скорее всего двоичные, потому что Z_OK это скорее всего код возврата GNU zip'ного libz.)
      Ответить
      • Еще прикольно, что возвращается всегда "". Т.е. функция бесполезна.
        Ответить
    • Как оно работает, если тут дважды вызывается free для buffer и data?
      Ответить
      • Видимо между строками 33 и 34 проебался return compressed.

        Вот, кстати, еще красивое говно: функция возвращает то литерал "" (который не надо освобождать) то буфер (который надо освободить). Всё для удобства вызывающего!
        Ответить
        • > Всё для удобства вызывающего!
          Особенно с учетом того, что в начале compressed'а лежит длина, у которой с вероятностью 1/256 (если little-endian архитектура) нолик в первом байте... Как они собираются отличать этот буфер от "" - хуй знает. Скорее всего так:
          char *result = stringFromDTM(dtm);
          if (result == "") { // не повторяйте это дома!
              // ...
          }
          Ответить
          • Интернирование строк?
            Ответить
            • Тип того. Но никаких гарантий, т.к. это всего лишь оптимизация для экономии места. Пользоваться этой фичей нельзя.
              Ответить
              • Теоретически пустая строка в сишечке может быть и нулевым указателем; и указателем на произвольный нулевой байт, лежащий где угодно (который можно сравнивать только через строковые функции); и специально подготовленным указателем на первую нулевую константу исполнимого модуля*, для которой сравнение с "" не лишено смысла.

                По-моему, маловато видов пустых строк... Надо ещё что-нибудь добавить.

                -----
                * При включенной оптимизации и при некоторых предположениях о линкере.
                Ответить
                • > Теоретически пустая строка в сишечке может быть и нулевым указателем
                  Данунахуй? А посоны и не знали.

                  > указателем на произвольный нулевой байт, лежащий где угодно
                  Именно так. А вот будет ли этот байт одним и тем же для каждого литерала - знают только линкер и компилятор.

                  P.S. А еще в древних гцц (3.х) была дурацкая опция -fwritable-strings.
                  Ответить
                  • Хе, в gcc 3.x еще одна забавная опция нашлась: -fthis-is-variable. Любители присваивать this будут довольны...
                    Ответить
                    • На 3.4 уже выпилили... Лучшее, что нашлось - 2.95, там оно депрекейтед, но еще работает:
                      void foo() {
                          test **t  = &this;
                          *t = new test(42);
                          bar(); // метод, на который эта херня всё-таки повлияет
                      }
                      Ответить

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