Джон Кармак о статическом анализе кода

    «Самой важной вещью, которую я сделал как программист за последние годы — это начал агрессивно применять статический анализ кода. — пишет Джон Кармак в статье, опубликованной на AltDevBlogADay. — Не так важны сотни серьёзных багов, которые удалось предотвратить, сколько смена ментальности и моего отношения к надёжности ПО и качеству кода».

    Джон Кармак рассказывает о различных инструментах, которые пытался использовать в течение своей карьеры и о тех выводах, к которым пришёл в итоге.

    С самого начала Кармак оговаривается, что качество кода — не самое важное в разработке ПО, и «признание этого факта не является каким-то моральным поражением. Ценность — вот что вы пытаетесь создать, а качество — всего лишь один из аспектов, наряду со стоимостью, функционалом и другими факторами. Было много чрезвычайно успешных и уважаемых игр, полных багов и постоянно вылетающих; так что применение стиля программирования космических челноков в игровой разработке было бы идиотизмом. Однако, качество всё равно имеет значение».

    Разработчик движка Quake говорит, что всегда старался писать хороший код, поскольку одной из его внутренних мотиваций было то, что как мастер своего дела он постоянно должен совершенствоваться. Кармак прочитал «кучу книг с занудными названиями» вроде «Политики, стандарты и планы качества», а сотрудничество с компанией Armadillo Aerospace позволило ему познакомиться с совершенно иным миром разработки ПО, где безопасность является критическим фактором.

    Знакомство Кармака с инструментами для статического анализа кода началось более десяти лет назад. Тогда, во время разработки Quake 3, он купил программу PC-Lint и опробовал её в деле. Однако, запуск из командной строки и необходимость продираться через кучу генерируемых комментариев совсем не понравились Кармаку. «Я сдался и довольно быстро забросил PC-Lint», — пишет он.

    Но в будущем всё-таки пришлось пересмотреть мнение, потому что кодовая база выросла на порядок, а код перевели с C на C++, так что в процессе миграции могли появиться новые ошибки. Несколько лет назад Кармак решил посмотреть, как изменились за прошедшие годы инструменты статического анализа кода.

    Первым делом, он подписался на демо-версию Coverity, это серьёзное ПО, у которого стоимость лицензии зависит от количества строк вашего кода, так что id Software вышла на пятизначную цифру. Программа проявила себя с лучшей стороны и сразу нашла с сотню ошибок. Кармак сразу отметил, что за десять лет многое изменилось, инструменты стали гораздо эффективнее в части соотношения сигнал/шум. Всё бы хорошо, но высокая цена всё-таки отпугнула.

    После этого протестировали библиотеку Microsoft /analyze, которая сейчас идёт в составе 360 SDK. Раньше эта библиотека была частью топовой баснословно дорогой версии Visual Studio, но сейчас доступна каждому владельцу 360 без дополнительной оплаты. «Я расцениваю это так, что для Microsoft качество игр для Xbox важнее, чем качество программ для Windows», — шутит Джон Кармак.

    Как оказалось, утилита от Microsoft проявила себя даже лучше Coverity по количеству найденных ошибок, хотя также дала большое количество ложных срабатываний. Джон Кармак в течение нескольких месяцев работал, постепенно исправляя найденные баги: сначала свой код, потом другой системный код, потом игровую часть. Эффект был колоссальным, нашлись очень важные ошибки, о которых в своё время попросту забыли, а также новые. Работа с включенной опцией /analyze просто обязательна для всех, она эффективно защищает от появления багов в процессе разработки.

    Поскольку инструмент от Microsoft использовался только для кода Xbox 360, всё ещё оставался открытым вопрос о том, что использовать для PC и PS3. Следующей попробовали программу PVS-Studio, которая отлично интегрируется с Visual Studio и имеет удобный демо-режим. По сравнению с /analyze, PVS-Studio показал себя чрезвычайно медленным инструментом, но он нашёл несколько дополнительных важных ошибок, в том числе логических — даже в коде, который был абсолютно чист с точки зрения /analyze. На сайте PVS-Studio есть ряд хороших статей с реальными примерами того, какие именно типы ошибок он может находить.

    Джон Кармак также дал второй шанс старому доброму PC-Lint, в связке с Visual Lint для интеграции с IDE. По старой доброй юниксовой традиции, этот инструмент может быть сконфигурирован для практически любой задачи, но на самом деле является весьма дружественным. И опять, даже в коде, который был чист после проверки и /analyze, и PVS-Studio, нашлись новые ошибки. Однако, с PC-Lint довольно трудно работать в том смысле, чтобы найти наиболее эффективные настройки по уровню выдачи предупреждений.

    В конце концов, Джон Кармак сделал несколько выводов, которые он советует понять и другим разработчикам. Во-первых, каждый должен признать, что в его коде существует множество ошибок. Это горькая пилюля, которую требуется проглотить каждому программисту. Во-вторых, ревизия кода должна быть обязательно автоматизирована. Приятно видеть ошибочные срабатывания автоматических систем на вашем коде, но на каждую ошибку автоматической системы приходится с десяток человеческих ошибок. Советы «писать лучший код», работать парами и так далее, тут не работают, особенно когда десятки программистов находятся в условиях нехватки времени.

    Кармак также отмечает, что PVS-Studio после каждого апдейта находит новые ошибки. То есть ошибки в коде вы никогда не сможете устранить до конца. В большом проекте они всегда будут, как статистические отклонения в свойствах физического материала. Вы можете только попытаться минимизировать их негативный эффект.

    Самой большой проблемой в C/C++, по крайней мере в нашем коде, говорит Кармак, являются NULL-указатели, на втором месте — ошибки формата строки printf. Большое количество серьёзных ошибок возникает в процессе модификации старого кода.

    Ну и напоследок Джон Кармак приводит цитату из твиттера Дейва Ревелла (Dave Revell): «Чем больше я использую статический анализ кода, тем больше удивляюсь, что компьютеры вообще загружаются».
    Метки:
    Поделиться публикацией
    Похожие публикации
    Комментарии 55
    • –1
      > ошибки формата printf
      о_О
      • +7
        Не верится как-то, что ошибки ввода/вывода — аж на втором (!) месте. Скорее, анализаторам их проще находить, вот и все.
        • +4
          В квейке то!?
          • +7
            sprintf, ваш КО
            • 0
              Зря удивляетесь. Допустим ситуацию:
              есть некая переменная long, после рефакторинга ее тип поменяли на unsigned long,
              а спецификатор в printf поменять забыли.

              Поверьте это не трудно.
              ПС: пример немного отдает синтетикой, но все же.
              • +1
                Чаще бывает ситуация когда для хранения размера чего-то был int, для поддержки 64-битных систем поменяли на size_t а в строке формата поменять забыли.
                • +1
                  Я же писал — пример синтетический.
                  • +2
                    А я предложил более реальный :-)
            • –23
              новая степень падения — ализар опустился до заказных рекламных постов…
              • +48
                Боже! Кармак рекламирует PVS!!1
                • +11
                  Он и сам в шоке
              • +10
                Разработчикам PVS фартануло — Кармак упомянул их продукт
                • +42
                  Да, приятно под новый год получить такой подарок! Но чтобы «фартануло» мы столько усилий приложили. Реализовывали пожелания, прикрутили Clang для скорости, писали статьи. Так что скорее приятно ощутить, что делается всё это не зря и приносит пользу. Везения тут 1%.
                  • +1
                    А вы своей PVS проверяли код PVS?
                    • +10
                      Постоянно и давно. Проверяем каждую ночь. Плюс в процессе разработки используем инкрементальный анализ (запускается в фоновом режиме после компиляции измененных файлов).
                    • 0
                      Мне было бы интересно, что PVS скажет о интерпретаторе Ruby. Может вам будет в будущем тоже будет интересно протестировать его.
                    • +1
                      Да, это точно, чтобы повезло, надо очень много усилий приложить перед этим. Правда, обычно этого не видят окружающие, думая, что «просто повезло».
                  • 0
                    Кстати, по поводу скорости работы: Советы по повышению скорости работы PVS-Studio.
                    • +5
                      сотрудничество с компанией Armadillo Aerospace позволило ему познакомиться с совершенно иным миром разработки ПО, где безопасность является критическим фактором.


                      Тут некорректно говорить о сотрудничестве, ведь он является основателем этой компании.
                      • +2
                        • +4
                          В одном из каментов пишут что SQLite отказался от static code analysis в пользу тестов и имеют 1000:1 покрытие. И типа у них все пучком.
                          Интерестно былобы чтоб PVS прогнали SQLite на предмет багов.
                          • +2
                            Вот честно, не знаю, проверяли или нет. Есть два варианта.

                            Вариант первый. Проект проверяли, но я про это забыл. Как я понимаю, проект маленький и мы могли в нем ничего не найти. Тогда факт его проверки выпал из головы.

                            Вариант второй. Мы не проверяли этот проект.

                            Покопался у себя в почте и записях. Нашел только вот это:

                            Нашел в SQLite3 следующий шедевр (встречается не раз)

                            //azCol имеет тип char*
                            int len = strlen(azCol? azCol: "");

                            Это лютый бешеный песец. Вызов strlen() (наверняка не встраивается) вместо того, чтобы написать 0 в коде. Должно было быть так:

                            int len = azCol? strlen(azCol): 0;

                            Полагаю, выявлять этот песец автоматом не сложно.


                            Это предложение на тему правил по оптимизации. Кстати, возможно этот человек проверял SQLite с помощью PVS-Studio и теперь нам уже там искать нечего… :)
                            • +3
                              Тесты выглядят как более дорогая вещь, статическая проверка какбе ничего не стоит разработчику, то есть не требуется писать какой-то дополнительный код в проект. В некоторых случаях очень сложно организовать покрытие тестами кода, который например отвечат за user interface/графику/сетевое взаимодействие/итд. Если у вас библиотека которой пользуются много пользователей есть время и смысл обложить ее всю тестами вдоль и поперек, а когда у вас реальный проект со сроками не совсем понятно зачем отказываться от статического анализа.
                          • +4
                            А вы как думали. Они наверное про консольный квейк. Представьте себе вы в консоли ввели
                            «move left; realgun; zoom 4; bum»
                            а тут у вас оказывается printf в игре заглючил, и все. смерть пришла
                            • НЛО прилетело и опубликовало эту надпись здесь
                              • 0
                                за поправку спасибо. но сути не меняется. главное с этим инструментом
                                zoom 4

                                А я скучаю за теми вренами когда игры делали для души. Сейчас игра мечны у продюсеров воспринимается как какое-то говнище. И слова им не скажи по поводу «мечты».

                                Но большинство идей современных игр придумано тогда: TTD, CIV,KB, KB2, DOOM — этот список можно дополнять сколько угодно. И играть было совсем не «бр...», благо тогда еще жены небыло и никто не ограничивал тебя по времени проведенному за игрой :-)
                                • НЛО прилетело и опубликовало эту надпись здесь
                                  • 0
                                    Были времена с флоппинетом. Когда сетка это была раскошь и основным способом писькомерки были сейвы скинутые на флоп.
                                • 0
                                  Как ни крути, получится MUD или Rogue-like :)
                                  • 0
                                    • +1
                                      Консоль в квейке очень даже активно использовалась. Редкий более-менее хороший игрок не прописывал себе в конфиг хотя-бы пару элементарных скриптов. Часто использовались скрипты для рокет-джампов (без направления, просто 2 кнопки одновременно), разных курсоров и сенсы для разного оружия, алерты команде с указанием местоположения, сообщение в виде текущего здоровья (когда одного убили, а у другого 1hp остался использовали) итд.
                                      Еще через консоль часто сервером управляли (голосовалки всякие, таймауты) и над ним-же издевались (g_gravity 0.1 итд). В общем, очень unixway игра была. В современной реинкарнации q3 такого уже не замечается.
                                      • 0
                                        в cs 1.6 наблюдается нечто похожее.
                                      • +1
                                        Надо подкинуть идею Шахиджаняну.
                                        • 0
                                          mplayer some_video.avi # наберём в консоли unix?
                                      • 0
                                        > когда десятки программистов находятся в условиях нехватки времени

                                        Такого рода проблемы генерируют большее количество ошибок, и особенно стратегических упущенний, чем может осилить статистический анализ кода. Поэтому статистический анализ эффективен только в условиях грамотного управления проектом
                                        • 0
                                          Хм, а что такое статистический анализ кода?
                                          • 0
                                            Это на BBM автотекст при вводе «помог» (
                                        • 0
                                          Это на BBM автотекст при вводе «помог» (
                                          • –1
                                            упс, не туда коммент вставил
                                          • +5
                                            Из вашей статьи пропал вывод Кармака:
                                            Если ваша версия Visual Studio включает /analyze, используйте его. В противном случае попробуйте PVS-Studio, возможно имеет смысл купить его.
                                            • 0
                                              На примере PC версии Rage видно, как замечательно работает его метод.
                                              • +3
                                                А в чём собственно проблема с Rage? Прошёл всю игру. Падений — было 1 раз за всё время. То, что были проблемы с драйверами, так тут в чём Кармак виноват — не он же дрова для видюх делает.
                                                • +1
                                                  На PS3 тоже драйвера виноваты?
                                              • –7
                                                Прекрасно, прекрасно. Этак уважаемый гуру скоро про TDD узнает — вот тогда гуляй, рванина.
                                                • +1
                                                  вы играли квейк? это наверное один с самых стабильных игр ever. Можете Джону про TDD рассказать и свой код показать. Он посмеется. Вот тогда гуляй, рванина.
                                                  • –3
                                                    Откуда вы беретесь, вьюноши со взором горящим, незнакомые ни с элементарными нормами русского языка, ни с понятием «ирония»?
                                                    Я, уважаемый, не только считаю кваку одной из величайших игр в истории, но и знаком с ее исходниками. Код Кармака быстр, эффективен — и ужасен(с точки зрения проектирования и читабельности). А вы, я так понимаю, с моими, раз так бодро рассуждаете?
                                                    • +4
                                                      Русский не родной, так что поправляйте по делу или не подёбывайте.

                                                      Проектирования и читабельность — субьективные понятия. Никто не будет покупать вашу программу или игру, если там будет изящнейшая архитектура или идеальное форматирование согласно GNU стилю отступов. Но это чепуха.

                                                      Куда-то вы от TDD увиливаете. Все, что я знаю о вашем коде, это то, что вы его _возможно_ пишите по методологии сначала тест, потом код. И это если бы Джон использовал этот подход при создании квейка, то никакого квейка бы не было.

                                                      На счет возраста даже отвечать вам не буду.
                                                      • 0
                                                        Это как раз вы куда-то увиливаете — я, заметьте, ни слова не сказал, и даже не намекал, что Кармак пишет плохие игры. Сказал как раз обратное.
                                                        Мой первый пост касался того, что мне показалось в заметке наиболее интересным и, вместе с тем, наиболее смешным — один из известнейших программистов в мире ВНЕЗАПНО открыл для себя, что код можно не только писать, но и читать, и, о ужас, анализировать. Утрирую, конечно.
                                                        Но нет, обязательно правдорубам вылезти и начать разоблачать в стиле «а ты сам-то кто такой?».
                                                • 0
                                                  Т.е. по мнению Джона важен именно результат который выполняет код, а не то как он при этом выглядит… Ну да — для игрушки которая в принципе должна быть интересной периодически возникающие баги (речь о минорных багах. Крэши просто выводят из себя особенно если не вовремя возникают) не столь важны как интересный геймплей. Однако программы могут нести не только игровые но и обучающие, рабочие функции где возникновение бага может очень дорого стоить.
                                                  Забавно, что был упомянут статический анализ кода, парное программирование, но не было упомянуто юнит тестирование и банальное «коде ревью» — это же более простые и дешевые способы существенно повысить качество кода.
                                                  • +1
                                                    Юнит тестирование и банальное «коде ревью» — это далеко не простые и далеко не дешевые способы повысить качество кода. Варианты «для галочки» — не в счёт. Я имею в виду, когда тестами покрыто 50% кода, а кодк ревью, это когда раз в неделю начальник просматривает код нового студента.
                                                    • 0
                                                      Однако — так уж получается, что в средней по уровню команде (в которой обычно есть студенты тоже) наиболее болезненные баги получаются именно из-за не правильного подхода к решению задач ( подхода к реализации, подхода к багфиксу) — т.е. просто из-за кривых рук.
                                                      А реализация юнит тестов хотя-бы на высоком уровне (20%) позволит вовремя заметить не менее серъезные ошибки.

                                                      Но трудные логические ошибки, которые глаз не видит или просто сотню мест (номера строк) где забыли проинициализировать переменные — конечно лучше увидит анализатор.
                                                      Поэтому использовать оный лучше при рефакторинге (либо просто оптимизации) кода или при возникновении багов, сценарий воспроизведения которых не постоянен.
                                                      • +7
                                                        Вы почему-то ищите серебряную пулю — один правильный лучший недорогой способ. Его просто нет. Надо использовать И код ревью, И парное программирование, И тесты, И статический анализ.

                                                        Тогда на вопрос: «Что вы сделали для того, чтобы было меньше ошибок?» у вас будет что ответить.
                                                        • 0
                                                          Есть один такой правильный лучший недорогой способ — не писать код. Как только от этого способа отказываются, сразу появляется простор для невыявленных ошибок.
                                                  • 0
                                                    Полный перевод статьи: Статический анализ кода. А оригинал теперь доступен здесь.

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