Разработчики Intel тоже говнокодят

    PVS-Studio vs IEC SDK
    В последнее время, рассказывая о проверке очередного проекта, я всё время повторял, что это очень качественный код и ошибок в нём практически не найдено. Примером может служить анализ таких проектов, как Apache, MySQL, Chromium. Почему мы выбираем такие приложения, я думаю понятно. Про них всех знают и никому не интересно, какие ужасы можно найти в дипломной работе студента Васи. Однако иногда мы поверяем и те проекты, которые просто случайно попали под руку. Некоторые такие проекты оставляют тяжёлые впечатления в моей тонкой и ранимой душе. В этот раз мы проверили Intel® Energy Checker SDK (IEC SDK).

    Intel Energy Checker SDK — это маленький проект на Си, содержащий всего 74500 строк кода. Для сравнения, размер проекта WinMerge составляет 186 000 строк кода, а размер проекта Miranda IM с плагинами около 950 000 строк кода.
    Intel Energy Checker SDK
    Кстати, пока мы находимся в начале статьи, попробуйте угадать, сколько в этом проекте может быть операторов 'goto'. Загадали число? Если да, то тогда продолжим.

    В общем, это один из маленьких, неизвестных широкой публике, проектов. Заглянешь в код такого проекта, и возникает следующая аналогия. Можно долго ходить по известным хорошим улицам и практически не видеть луж. Но стоит свернуть с улицы и заглянуть во двор, как лужа не только сразу находится, так не понятно, как вообще можно пройти, не намочив ноги.

    IEC SDK вполне можно отнести к проектам, рассматривая текст которых, в голове всплывает слово "говнокод". Не скажу, что код ужасен, бывает намного хуже. Но смотрите сами. Во всем проекте всего 247 функций. Скажете мало? Конечно, мало. Зато размер некоторых из них шокирует. Четыре функции вообще имеют размер более 2000 строк:

    V553 The length of 'pl_open' function's body is more than 2000 lines long. You should consider refactoring the code. pl_csv_logger productivity_link.c 379

    V553 The length of 'pl_attach' function's body is more than 2000 lines long. You should consider refactoring the code. pl_csv_logger productivity_link.c 9434

    V553 The length of 'main' function's body is more than 2000 lines long. You should consider refactoring the code. cluster_energy_efficiency cee.c 97

    V553 The length of 'main' function's body is more than 2000 lines long. You should consider refactoring the code. pl2ganglia pl2ganglia.c 105

    Показателен и вот такой способ получения длины имени директории:
    #define PL_FOLDER_STRING "C:\\productivity_link"
    #define PL_PATH_SEPARATOR_STRING "\\"
    #define PL_APPLICATION_NAME_SEPARATOR_STRING "_"
    ...
    pl_root_name_length = strlen(PL_FOLDER_STRING);
    pl_root_name_length += strlen(PL_PATH_SEPARATOR_STRING);
    pl_root_name_length += application_name_length;
    pl_root_name_length += strlen(PL_APPLICATION_NAME_SEPARATOR_STRING);
    pl_root_name_length += PL_UUID_MAX_CHARS;
    pl_root_name_length += strlen(PL_PATH_SEPARATOR_STRING);

    Я понимаю, что это место не критично для скорости и нет смысла оптимизировать расчет длины строк. Но просто из любви к искусству, можно было бы завести для этого вот такой макрос "#define STRLEN(s) (sizeof(s) / sizeof(*s) — 1)". Ещё больше моё чувство прекрасного страдает от того, что я вижу строку, содержащую «C:\\». Меня настораживают подобные макросы:
    #define PL_INI_WINDOWS_FOLDER "C:\\productivity_link"
    #define PL_INI_WINDOWS_LC_FOLDER "c:\\productivity_link"
    #define PLH_FOLDER_SEARCH _T("C:\\productivity_link\\*")


    Впрочем, этот код делает то, что нужно и не будем заострять внимание на стиле программирования. Гораздо больше пугает то количество ошибок, которые нашел PVS-Studio в проекте такого маленького размера. При этом стоит учитывать, что проверено далеко не 74000 строк кода. Около трети кода предназначено для LINUX/SOLARIS/MACOSX и находится в #ifdef/#endif ветках кода, которые не проверялись. Непроходимый лес из #ifdef/#endif вообще отдельная тематика, но я обещал больше не говорить об оформлении кода. Желающие могут сами заглянуть в исходные коды.

    В коде IEC SDK собран разнородный букет из ошибок, которые можно допустить, оперируя с массивами на низком уровне. Впрочем, ошибки такого рода очень типичны для языка Си.

    Есть код, обращающийся к памяти за пределами массива:

    V557 Array overrun is possible. The '255' index is pointing beyond array bound. pl2ganglia pl2ganglia.c 1114
    #define PL_MAX_PATH 255
    #define PL2GANFLIA_COUNTER_MAX_LENGTH PL_MAX_PATH
    
    char name[PL_MAX_PATH];
    
    int main(int argc, char *argv[]) {
      ...
      p->pl_counters_data[i].name[
        PL2GANFLIA_COUNTER_MAX_LENGTH
      ] = '\0';
      ...
    }

    Имеем дело с классическим дефектом записи терминального нуля за пределами массива. Должно быть:
    p->pl_counters_data[i].name[
       PL2GANFLIA_COUNTER_MAX_LENGTH - 1
    ] = '\0';

    Есть ошибки обнуления структур.

    V568 It's odd that the argument of sizeof() operator is the '& file_data' expression. pl_csv_logger productivity_link_helper.c 1667

    V568 It's odd that the argument of sizeof() operator is the '& file_data' expression. pl_csv_logger productivity_link_helper.c 1831

    V512 A call of the 'memset' function will lead to underflow of the buffer 'pconfig'. pl_csv_logger productivity_link_helper.c 1806

    Пример подобного некорректного обнуления:
    int plh_read_pl_folder(PPLH_PL_FOLDER_INFO pconfig) {
      ...
      WIN32_FIND_DATA file_data;
      ...
      memset(
        &file_data, 
        0, 
        sizeof(&file_data)
      );
      ...
    }

    Плохо пойдет работа по поиску файлов, если использовать структуру WIN32_FIND_DATA с мусором внутри. Впрочем, есть подозрение, что Windows версия этого произведения программистского искусства мало кого интересует. Например, код компилируется в режиме «Use Unicode Character Set», хотя он на это рассчитан не до конца. Видимо, никто и не задумывался. Создали проект для Visual Studio, а по умолчанию настройка «Character Set» как раз задает использование UNICODE.

    В результате, имеем c десяток мест, где строки очищаются только частично. Приведу только один фрагмент подобного кода:

    V512 A call of the 'memset' function will lead to underflow of the buffer '(pl_cvt_buffer)'. pl_csv_logger productivity_link_helper.c 683
    #define PL_MAX_PATH 255
    typedef WCHAR TCHAR, *PTCHAR;
    TCHAR pl_cvt_buffer[PL_MAX_PATH] = { '\0' };
    
    int plh_read_pl_config_ini_file(...)
    {
      ...
      ZeroMemory(
        pl_cvt_buffer, 
        PL_MAX_PATH
      );
      ...
    }

    Впрочем, есть места, где и отключение UNICODE не поможет. Здесь вместо текста будет распечатано что-то непонятное:

    V576 Incorrect format. Consider checking the second actual argument of the 'wprintf' function. The pointer to string of wchar_t type symbols is expected. producer producer.c 166
    int main(void) {
      ...
      char *p = NULL;
      ...
    #ifdef __PL_WINDOWS__
      wprintf(
        _T("Using power link directory: %s\n"), 
        p
      );
    #endif // __PL_WINDOWS__
      ...
    }

    Поясню. Функция wprintf ожидает строку типа «wchar_t *», а ей будет передана строк типа «char *».

    Есть и другие ошибки, и небольшие ляпы, похожие на этот:

    V571 Recurring check. The 'if (ret == PL_FAILURE)' condition was already verified in line 1008. pl_csv_logger pl_csv_logger.c 1009
    if(ret == PL_FAILURE) {
      if(ret == PL_FAILURE) {
        pl_csv_logger_error(
          PL_CSV_LOGGER_ERROR_UNABLE_TO_READ_PL
      );

    Стараться перечислить все замеченные недочеты не вижу смысла. Если кто-то захочет, то я могу предоставить ключ для проверки проекта и анализа сообщений. Авторам SDK я также отправлю описание ошибок.

    А теперь десерт


    Помните, в начале, я просил загадать, сколько в проекте можно найти операторов 'goto'. Так вот, я думаю ваше число далеко от истины. Всего в проекте используется 1198 операторов goto. Один оператор goto на 60 строк кода. А я думал, что подобный стиль уже канул в небытие.

    Заключение


    А что собственно этой статьёй хотел сказать автор? Интелу СРОЧНО нужно внимательно присмотреться к PVS-Studio. :-)
    PVS-Studio
    Статический анализ кода для C, C++, C# и Java

    Комментарии 116

      +27
      А что вы хотите, индийцам тоже нужно чем-то на хлеб зарабатывать.
        –14
        Палец вверх за goto!
        (Пародия на this is horosho)
          +1
          Это означает скорее всего то, что программистов быстро переучивали с бейсика (или фортрана), причем с очень старого, где GOSUB было юзать не принято :)
          +22
          В коде ядра Linux тоже есть goto. Все дело в том каким образом в коде на Си конкретное goto применяется и по умолчанию goto в Си говнокодом не является.
            +5
            Если судить по другим мейнстрим языкам, то проблемы goto обходяться другими алгоритмичискими решениями. Согласитесь, все же 1 goto на 60 строк — это многовато…
              +15
              Если он даёт прирост производительности и не создаёт уязвимостей, то говнокод это использование громоздких, медленных и тяжёлых конструкций вместо лаконичного и шустрого goto
                +3
                еще пример где без goto не обойтись (по крайней мере я не вижу как) — выход из трех вложенных циклов. Зачем делать три вложенных цикла — другая тема)
                  –2
                  Например завести флаг и проверять его в каждом цикле.
                    +2
                    освобождение ресурсов — другой неплохой пример (в ядре линукса с той целью обычно и используется).
                      0
                      Один JMP заменится на цепочку JNZ/JNE. В принципе, конечно, не средство экономии…
                        0
                        интересно, надо будет проверить на досуге)
                          0
                          в основном это как стриптизерша — смотри, но не трогай.
                        +3
                        Конечно если эти три вложенных цикла не размазаны на 2000 строк кода…
                          0
                          И если goto не перекрестные
                      +3
                      Я скорее соглашусь с вами. Но я кода не видел этого проекта. Может быть что каждые 60 строк кода им надо освобождать ресурсы и это удобно делать в Си с goto. А за 60 строчек можно много ресурсов наполучать от ОС…
                      Кстати можно было бы в вашем анализаторе более детальный анализ goto сделать. А то для проектов на Си это актуально. По крайней мере в обзоре было написано только что их много, а еще бы хотелось знать где и почему в коде проекта они используются неправильно.
                        +1
                        Правил с goto сейчас в PVS-Studio нет, так как сам по себе goto ошибкой не является. Конечно, легко сделать ошибку в запутанном коде с переходами туда-сюда. Но там даже человеку сложно понять, что задумывал автор и что получилось. Так что пока идей, как код с goto анализировать не было.

                        То что много goto, это я просто глазами заметил. А потом посчитал и вообще удивился.
                        0
                        Знаете, я тоже думал, что использование goto — плохой тон. Но потом понял, что это, пожалуй, самый изящный способ выхода из вложенных циклов в большинстве языков.
                          +1
                          Точно. Вот в питоне нет goto – вместо него пользуют страшное… Exception'ы. Но это даёт ещё один уровень вложенности, что не есть хорошо.
                            0
                            А что-нить типа break(3)?
                            • НЛО прилетело и опубликовало эту надпись здесь
                                0
                                В Java для этого есть break и continue с меткой на цикл, из которого выходишь или выполнение которого продолжается с новой итерации.
                                  0
                                  Кстати, очень полезная конструкция.
                                  Хотя и ненаглядно, т.к. метка ставится перед началом цикла, а переход происходит в его конец.
                                +1
                                это тот же goto, но более тупой и дающий море возможностей перепутать магическую тройку с магической двойкой или 3.14.

                                если вы понимаете, в набор какий опкодов компилится сишечный код, использование goto — более чем естественно

                            +2
                            Он там для обработки ошибок вроде используется, т.к. в Си нет исключений. Фактически goto может пригодиться только для досрочного выхода из блока. Все остальные способы использования goto можно назвать быдлокодом.
                              +3
                              >Он там для обработки ошибок вроде используется, т.к. в Си нет исключений.

                              в основном — да, для обработки ошибок, но на самом деле — где надо, там и используется, а не где мама разрешила.

                              и возврат в начало функции бывает и выход из цикла чуть дальше его конца (аналог for-break-else) и просто пропуск нескольких блоков когда.

                              хотя бы потому, что три уровня вложенности в функции на 20 строк — намного больший ппц, чем красивый локальный переход. вобщем, имеющий grep. да увидит.
                          • НЛО прилетело и опубликовало эту надпись здесь
                              +26
                              если я не ошибаюсь — то это богиня покровительствующая программированию, одно упоминание ее имени в коде защищает проект от багов/лагов примерно на 75%
                                +2
                                Надо переименовать и повторно прогнать PVS-Studio. Ошибок должно стать в 3 раза больше.
                                  +2
                                  Не в 3, а в 4 ;)
                                    +1
                                    Это смотря во что переименовать. Если в "{<,=;" то ошибок и вправду станет значительно больше.
                                –15
                                Чем плохи функции >2000строк?
                                  0
                                  Средняя курсовая работа студента поместиться в одну такую :)
                                    0
                                    В исходниках Андроид — Java классы по 10000 строк кода. И это скорее всего нормально. Просто люди не хотят создавать лишних абстракций, лишних подпрограмм (функций) там где они не нужны. Они написали класс-сервис на 10К строк, который делает законченную вещь. Внутри его делить и абстрагировать видимо нет смысла. Экономия времени и денег на лицо.
                                      +5
                                      Java классы по 10000 строк кода? Или класс, число строк в методах которого превышает 10000?
                                      В первом случае, мне кажется, что это классический big ball of mud, хотя если они этими классами умудряются не нарушить SRP и ISP, то это здорово (хотя я думаю, что если программист решился на такое, то это подразумевает, что больше никто и никогда в этот класс не полезет).
                                      Во втором случае — это абсолютно нечитабельное самоубийство. Потребуется немало времени тому, кто попытается разобраться, что же там происходит. И, думаю, что в этом случае это метод почти наверняка не покрыт тестами, так как тестировать такой метод невероятно сложно.
                                        +1
                                        > Или класс, число строк в методах которого превышает 10000?
                                        Я имел в виду «число строк каждого из методов».
                                          +3
                                          Часто заглядываю в исходники API, такого класса пока не встретил, или это не в API? Можно хоть один пример?
                                            0
                                            Можно ссылку на исходники?
                                            Мне лично слабо верится, что методы длиной >10000 строк нельзя декомпозировать, сделав код более читабельным.
                                            0
                                            Вобщем там все хорошо разделено в коде по ответственности классов. Например: имеем сервис окружения ОС, например activity manager. Он выполняется в виде класса, который позволяет делать RFC вызовы к себе, а внутри него уже 10к строк. Точно название класса я сейчас не скажу, в котором это видел. Но это точно правда. Там вобще все файлы с кодом «большие», не зависимо Java 'то или C/C++. Тесты там тоже есть. Например есть большой compatability suit (вроде так называется), его можно собрать вместе с самим Android и запустить на девайсе. Он тестирует все подсистемы окружения ОС, написанные на всех языках. Если все подсистемы отработали по тестам — то девайс совместимый.
                                            Также можно заметить что в исходном коде окружения Андроид ничего не указывает на то что он писался с использованием каких-либо IDE. То есть файлов какой-либо IDE или автоматически сгенерированных ими замечено не было. Там еще в системе сборке (написанной на make, руками) есть генераторы разных файлов.
                                              0
                                              Не, там классы вместе с реализацией методов на 10к строк.
                                                +3
                                                Хорошо, убедили. Давайте будем писать весь код в одном классе. И функций пусть тоже будет поменьше.
                                                  –7
                                                  Ну это дело каждого. Главное чтобы в команде согласие было.
                                              +2
                                              бох мой — думаю, эти классы в 10 000 кода и не тестируются. У меня был проект, где правые английские парни наколбасили таких классов под 20 000 строк. Мы с командой такой проект два года переделывали, чтобы он хоть как то тестировался автоматизированно.
                                            +4
                                            Попробуйте их посопровождать.
                                            • НЛО прилетело и опубликовало эту надпись здесь
                                                +1
                                                Тоже верно. Но там всего 75к строчек кода и из них 5 функций по 2 и более тыщи строк. Т.е. получается, что в этих функциях помещается не много не мало но 1/7 часть кода.
                                                  +14
                                                  Часто после такого разбиения ради разбиения ВНЕЗАПНО оказывается что код можно использовать во многих местах. А потом его ещё раз разбиват, и ещё. Выделяют из него классы, хелперы… И оказывается что этот код на 2000 строк состоит из цепочки 3-х методов по 15 строк, и 10 сторонних методов и классов, которые используются в разных местах системы и в общем-то универсальны. Это и называется рефакторинг.
                                                  • НЛО прилетело и опубликовало эту надпись здесь
                                                      0
                                                      «Большой switch плюс куча ifdef» почти всегда красиво решаются правильной иерархией классов и полиморфизмом.
                                                      • НЛО прилетело и опубликовало эту надпись здесь
                                                          0
                                                          А кто говорил, что использование ОО кода будет простым и интуитивным? :) Бонус ООП скорее в гибкости и упрощении разработки/поддержки кода, а не в простоте его использования. А для упрощения уже каждый может добавить обёрток под свои нужды.

                                                          Больших switch и т.п. иногда можно избежать с помощью более высокоуровневых инструментов, например, вместо ручного парсера использовать генераторы. Опять же, не факт что получившийся код будет проще, но его будет легче писать и поддерживать за счёт более ограниченного и чистого синтаксиса.
                                                          • НЛО прилетело и опубликовало эту надпись здесь
                                                              0
                                                              Я же специально разделяю внутреннюю поддержку кода и его внешнее использование. На вашем примере restkit, снаружи было бы проще позвать одну функцию с нужными параметрами, чем городить непонятные объекты. Изнутри же более удобно этим управлять, когда код чётко разделён по классам, плюс это более гибко.

                                                              Парсер я привёл лишь в качестве примера высокоуровневого инструмента, упрощающего код для конкретной задачи, ничто ведь не мешает использовать что-то аналогичное и для выполнения байткода.
                                                            +1
                                                            На счёт ifdef и парамаетров компиляции. Приведу пример: у нас есть класс CFileOperations с десятком методов по копированию, удалению, перемещению файлов и т.д. Класс должен работать под Linux, Windows и MacOS. Поэтому в каждом методе есть 3 блока вида «ifdef WIN… end if». Класс огромен и страшно читаем.

                                                            В тоже время можно было бы создать интерфейс IFileOperations и 3 реализации под разные ОС. В итоге:
                                                            -у нас на весь код был бы только 1 блок «ifdef»
                                                            -при добавлении методов количество «ifdef» не увеличивается
                                                            -в каждом классе собран код только под одну ОС — читать легко и приятно
                                                            -если мы забудем после добавления очередного метода написать реализацию под определенную ОС — нам об этом скажет компилятор, а не загадочное поведение на рантайме.

                                                            Я, конечно, не отрицаю случаев когда такой подход не катит, но частенько — катит.
                                                            • НЛО прилетело и опубликовало эту надпись здесь
                                                                0
                                                                К сожалению, с питоном не знаком, поэтому дальше судить не берусь. Вполне вероятно, что там и вправду без этого никак.
                                                                • НЛО прилетело и опубликовало эту надпись здесь
                                                      +1
                                                      Чем больше функция — тем сложнее понять что она делает. Чем сложнее понять — тем больше вероятность, что при ее изменении будет допущена ошибка. Разбивать имеет смысл хотя бы ради этого.
                                                        +16
                                                        Чтобы было легче ориентироваться в этих функциях, они используют заметные комментарии :-)
                                                        /*
                                                         @@@@@   @@    @@@@   @@@@
                                                           @    @  @  @    @ @    @
                                                           @   @    @ @      @
                                                           @   @    @ @       @@@@
                                                           @   @@@@@@ @  @@@      @
                                                           @   @    @ @    @      @
                                                           @   @    @  @@@@  @@@@@
                                                        */
                                                        
                                                        //-------------------------------------------------------------------------
                                                        //   @    @    @ @@@@@  @   @
                                                        // @ @ @  @@   @   @     @ @
                                                        //  @@@   @ @  @   @      @
                                                        // @ @ @  @   @@   @     @ @
                                                        //   @    @    @ @@@@@  @   @
                                                        //-------------------------------------------------------------------------
                                                        

                                                          +20
                                                          Супер :)

                                                          	/*
                                                          	@    @   @@   @@@@@  @    @        @       @@@@   @@@@  @@@@@
                                                          	@@  @@  @  @    @    @@   @        @      @    @ @    @ @    @
                                                          	@ @@ @ @    @   @    @ @  @        @      @    @ @    @ @    @
                                                          	@    @ @    @   @    @ @  @        @      @    @ @    @ @@@@@
                                                          	@    @ @@@@@@   @    @  @ @        @      @    @ @    @ @
                                                          	@    @ @    @   @    @   @@        @      @    @ @    @ @
                                                          	@    @ @    @ @@@@@  @    @        @@@@@@  @@@@   @@@@  @
                                                          	*/
                                                          
                                                          • НЛО прилетело и опубликовало эту надпись здесь
                                                        0
                                                        в первую очередь своим размером
                                                          0
                                                          А еще попробуйте нанимать не неё юнит-тест. :)
                                                            0
                                                            Наверное тем, что цикломатическая сложность высокая, и как следствие гарантировать отсутствие багов в ней невозможно
                                                            +5
                                                            А вот могу тоже привести кусочек C#-говнокода, обнаруженный в коде реального проекта компании, известной и старой не менее, чем Интел.

                                                            И это не прикол — это реальный код.

                                                            string s = Request.QueryString["action"];
                                                            // s may have "remove" or "restore" values

                                                            switch (s[2])
                                                            {
                                                            case 's':
                                                            case 'S':
                                                            ..............
                                                            break;

                                                            case 'm':
                                                            case 'M':
                                                            ..............
                                                            break;

                                                            }
                                                              0
                                                              Можно еще оптимизировать:

                                                              char c = Request.QueryString["action"][2];
                                                              // c may have 'm' or 's' values, lol
                                                              
                                                              switch ©
                                                              ...
                                                              
                                                                –2
                                                                Особенно если Request.QueryString["action"] может вернуть пустую строку.
                                                              +6
                                                              Надеюсь вы НЕ отправили баг-репорт! Индийский говнокод вряд ли что исправит, а вы только нарушите тонкий баланс ошибок позволяющий программе работать.
                                                                +16
                                                                Без этой картинки, пост был бы не полноценным :)

                                                                image
                                                                  –1
                                                                  Разработчики Intel тоже говнокодят

                                                                    +20
                                                                    Разработчики Intel тоже говнокодят
                                                                    … можно было бы завести для этого вот такой макрос "#define STRLEN(s) (sizeof(s) / sizeof(*s) — 1)"

                                                                    Стоит ожидать топика?
                                                                    Разработчики PVS-Studio тоже говнокодят

                                                                      –1
                                                                      +1
                                                                        +2
                                                                        Прошу, попробуйте написать вычисление длины пути хорошо. А мы обсудим Ваше решение.
                                                                          0
                                                                          Легко. Вот смотрите:
                                                                          CString str = _T(«Тут:\Какой-то\путь»);
                                                                          int len = str.GetLength();
                                                                            0
                                                                            К стати, сам первый постебусь с неэкранированных слешей :)
                                                                              +3
                                                                              Это Си++. На Си прошу пример в студию. :)
                                                                            –5
                                                                            По-вашему терминальный нуль просто так придумали?
                                                                              +4
                                                                              Что?
                                                                                –3
                                                                                Мы на разных языках говорим? Зачем по-вашему '\0' помещают в конец строки?
                                                                                  +2
                                                                                  А как Вы думаете, почему Ваши вопросы минусуют, а мои плюсуют? И еще подумайте, что должен возвращать макрос, называющийся STRLEN.
                                                                                    0
                                                                                    По-моему вы чересчур преисполнены самомнением для человека, который для вычисления длины строки советует использовать макрос
                                                                                    #define STRLEN(s) (sizeof(s)/sizeof(*s) — 1)
                                                                                    Я поясню свои вопросы: (Null Terminator) '\0' — маркер окончания последовательности символов, хранящихся в памяти и составляющих данную строку. Таким образом длину строки, хранящейся в памяти, можно определить как разность смещений начала строки и терминального нуля, относящегося к данной строке.
                                                                                    Для препроцессоров компиляторов C/C++ строка является единым токеном, поэтому невозможно вычислить длину строки at compile time, используя macro expansion trickery.
                                                                                    Как бы я реализовал «вычисление длины пути хорошо»? Пожалуй что так.
                                                                                      +1
                                                                                      Написали бы сразу, что не знаете как работает оператор sizeof.
                                                                                        –2
                                                                                        Ещё один. С чего вы взяли, что я не знаю как работает оператор sizeof?
                                                                                        Суть моих ответов сводится к тому, что НЕВОЗМОЖНО определить длину строки at compile time, что безуспешно пытается сделать уважаемый Andrey2008. Это можно сделать только at run-time, к примеру, с помощью strlen.
                                                                                          +1
                                                                                          Это же строковая константа, и её размер компилятор знает.
                                                                                            +1
                                                                                            Было бы невозможно, вот только уважаемый Andrey2008 успешно определяет длинну константной строки:
                                                                                            #define PL_FOLDER_STRING "C:\\productivity_link"
                                                                                            #define PL_PATH_SEPARATOR_STRING "\\"
                                                                                            #define PL_APPLICATION_NAME_SEPARATOR_STRING "_"
                                                                                              0
                                                                                              Господа, приношу свои извинения! В заблуждение ввело то, каким образом могут обрабатываться строковые литералы:

                                                                                              char c = *"Brown fox jumps over the lazy dog";

                                                                                              Отдельные извинения для Andrey2008! Не сразу обратил внимание, что приведённый макрос предлагается использовать для литералов.
                                                                          +2
                                                                          Отнюдь не пытаясь оправдаться за весь Интел, упомяну, что данный SDK взят со страницы whatif.intel.com. Как известно, там лежат даже не прототипы, а так — программки, некоторым из которых когда-либо суждено стать прототипами. Многие наброски и черновики сделаны студентами-практикантами, которых уже вычеркнули из книги судеб.

                                                                          Там кстати специально написано: «What if software were like this?» ;)

                                                                          Впрочем, это ничуть не меняет сути поста: код должен быть красивым, надежным, и в обязательном порядке проверенным статическим анализатором. Например, Klocwork или PVS Studio :)
                                                                            +1
                                                                            Я понимаю, что это полупрототипы. И что присматриваться к ним не стоит. Но не удержался, и изучил «Intel Energy Checker SDK Primary Technology Contacts»:

                                                                            Jamel Tayeb, Applications Engineer. Jamel Tayeb is a software engineer in Intel's Software and Services Group. He has held a variety of engineering, marketing and PR roles over his 10 years at Intel.

                                                                            Kevin Bross, Modular Systems Architect. I've worked for Intel for 20 years in a variety of engineering, marketing, and architectural roles.

                                                                            Действительно, студенты-практиканты. :-)
                                                                              0
                                                                              Ну во-первых, переходить на дичности как-то совсем уж некрасиво… А во-вторых, ниужели вы думаете что System Architect в Интеле код пишет?
                                                                                0
                                                                                Не говоря уже о Applications Engineer :)
                                                                            +4
                                                                            Я почти угадал — загадывал тысячу, ибо на C очень удобно обрабатывать ошибки, исползуя код вида:

                                                                            int somefunc(...)
                                                                            {
                                                                              if (something_erroneus)
                                                                                goto ERROR;
                                                                              ...
                                                                              do_something();
                                                                              ...
                                                                              if (something_else_failed)
                                                                                goto ERROR;
                                                                             
                                                                              return 0;
                                                                            
                                                                            ERROR:
                                                                              ... // free the resources, null the output arguments etc.
                                                                             return ERROR_CODE;
                                                                            }
                                                                            
                                                                              –3
                                                                              Все таки лучше иметь один return в функции.
                                                                                +3
                                                                                Стоп-стоп, без фанатизма. Не стоит воспринимать рекомендации буквально: если говорят, что лучше иметь одну точку выхода из функции, это ещё не значит, что нужно весь код писать так, чтобы в каждой функции был ровно один return. Правила, придуманные человеком, в этом смысле не эквивалентны законам физики, ибо есть возможность выбора, и ей нужно пользоваться с умом. Ну, и учитывайте специфику языков: что позволено Юпитеру C'шнику, то не позволено плюсовику, так сказать.
                                                                                  0
                                                                                  Как раз в обработке ошибок это удобно, так как можно выполнить действия по выходу из функции, файл закрыть или мьютекс разблокировать.
                                                                                    0
                                                                                    я вот недавно в книжно магазине видел экземпляр, полный догматический заявлений типа «Не возвращайте из функции NULL, кидайте эксепшны» и мотивировалось это только тем, что NULL нужно будет обработать(как будто на эксепшн можно забить). Жаль название и автора не запомнил.
                                                                                      0
                                                                                      На NULL действительно нужно будет проверять, и самое главное — не забыть этого сделать. А исключение «проверять» не нужно, в этом и преимущество.
                                                                                        –1
                                                                                        Да
                                                                                  +3
                                                                                  А я загадал 1200 и таки почти угадал =)

                                                                                  А все потому, что по долгу службы мне приходится работать с одним адским проектом, который содержит в своем череве некоторого монстра, реализующего транспортный уровень. За все мои 15 лет айтишного прошлого я не видел говнокода страшнее и махровее чем там. Лес дефайнов, километры свичей, частокол goto — все можно найти там. Коду 20 лет и его приходится поддерживать и портировать на разные платформы. И это ужасно, скажу я вам. А еще ужаснее то, что заказчик считает что все прекрасно и ничего страшного в этом нет. Just a business…

                                                                                    0
                                                                                    Если описанный вами проект написан на C++, то я вам очень сочувствую: на предыдущей работе я попал в точно такую же ситуацию — и goto, и switch на три-четыре экрана, макросы, «ООП» на структурах (коих по одной на сущность — никаких абстракций и наследования), функции на сотни строк (а одна была даже на ~3800). Будущее выглядело примерно таким же. Но мы нашли общий язык с начальством: я написал заявление, и больше там не работаю, а занимаюсь любимым делом, ха-ха (:
                                                                                      0
                                                                                      Че-то Вы быстро сдались. Я тоже в подобных ситуациях бывал. Тут все просто — свой кусок начинаешь писать правильно, в тех местах, где он примыкает к другому коду — подправляешь тот код. Тесты, конечно же, контроль версий и т.д. Так тихой сапой за полгодика можно привести в чувство самый мертвый код.
                                                                                        0
                                                                                        Рефакторить без тестов получается не всегда, а тесты, в свою очередь, не всегда можно повесить на хреновый код(отличный тут пример — в веб приложениях каша из логики и представления). Так и работаешь, постоянно восстанавливая тонкий баланс проекта, после каждой добавленной строчки кода. Чувствуешь себя той самой бабочкой, взмах крыла которой, несет катастрофы, мор, отчаяние.
                                                                                          +1
                                                                                          Да, именно так и делается. Ощущаешь себя мужиком с мачете в джунглях =) Вгрызаешься в код, начинаешь окультуривать. Ну и так потихонечку-полегонечку. Вот только все равно нет никакой гарантии что не вылезет какая-нибудь очередная бяка за день до релиза.
                                                                                            0
                                                                                            Тут ещё нужно чтобы мотивации хватило, иногда посмотришь на это всё и руки опускаются. Думаешь, мол, вот устроил же себе развлечение, а ведь можно было просто ещё чуть фигни добавить, никто бы и не заметил ;)
                                                                                            0
                                                                                            У меня не было полгода времени и столько же терпения. Тем более, это был fatality, а предпосылки были ещё до этого чудо-проекта.
                                                                                            +2
                                                                                            Да, именно на С++. Но много и реликтовых кусков на Си. Причем «аффтар» сего творения до сих пор не упокоился работает в команде и продолжает писать. Самое жуткое, что вот я смотрю на его код 20-летней давности и тот, что он написал буквально вчера… ну никакой разницы! Он прямо начинает излагать говнокодом, представляете? Ладно, если вся эта трехомудия образуется в результате патчинга-перепатчинга и затыкания ошибок… но в данном случае она зарождается прямо изначально. Это выше моего понимания.

                                                                                            Мне страшно оттого, что некоторые люди за \d0 лет практики продолжают как ни в чем ни бывало писать ТАКОЕ. Поэтому я очень осторожно отношусь к стажу («он еще в 80х начинал»), как показателю опыта и качества.
                                                                                            0
                                                                                            Зато у вас есть работа. Может быть, еще на 20 лет…
                                                                                              +1
                                                                                              У меня большие подозрения, что тот товарищ так же думал, когда писал этот код
                                                                                            0
                                                                                            К слову, в славной платформе Samsung Bada обработка «исключений» осуществляется именно так.

                                                                                            Найдите отличия: developer.bada.com/help/topic/com.osp.devguide.help/html/basics_bada_programming/exception_propagation.htm
                                                                                            +3
                                                                                            Вообще, кто кодит на ASM и на C одновременно, их должно не покидать чувство, что это очень близкие языки. И C хорош тем, что он ближе к ASMу, чем, например, Pascal или Java. Так вот чем ближе к машинному коду, тем уместнее конструкция GOTO, ведь процессор по сути то и делает, что «прыгает» от инструкции к инструкции, с помощью тех самых GOTO (безусловных JMP и условных JE, JNE...). Очевидно, что во многих случаях GOTO позволяет сократить кол-во строк кода и соответственно процессорное время.
                                                                                              0
                                                                                                0
                                                                                                ну ладно, из них 10273 в ext/date/lib/parse_date.c.orig, сгенерированном re2c
                                                                                                  0
                                                                                                  блин, и еще 10273 в ext/date/lib/parse_date.c
                                                                                                  так неинтересно)
                                                                                                +1
                                                                                                Да ладно, все говнокодят. Другое дело, что одни потом свой говнокод исправляют, а другие нет. И ещё одни учатся писать правильно, а другие так и говнокодят до конца жизни.
                                                                                                • НЛО прилетело и опубликовало эту надпись здесь
                                                                                                      +1
                                                                                                      Нет ничего удивительного, что в гигантах есть места для инду/ази/говно кода.
                                                                                                      В своё время тоже сильно удивлялся способностям Senior' ов из Редмонда (название организации додумайте сами). Программируя на C++ люди, которые были ответствененны за инфрасруктуру, копировали refernces на объекты параметры методов, отчего в определённые моменты, например, падали ВСЕ тесты в проекте.
                                                                                                      Потом весь TFS вставал на уши.

                                                                                                      Вся эта история может быть вызвана как бюрократией (мы направляем Васю Пупкина на этот проект и всё тут) так и сложностью с людскими ресурсами ресурсами, так и проблемой условного апгрейда кадров (Вася Пупкин работает уже 20 лет у нас, давайте дадим ему Senior и отправим на проект с неизвестными ему технологиями).
                                                                                                        0
                                                                                                        350 — в три раза ошибся.

                                                                                                        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                                                                        Самое читаемое