| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Для новичков > Проверка open-source игры Multi Theft Auto |
| Автор: Thunderbolt 16.8.2013, 14:14 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Мы давно не проверяли игры с помощью PVS-Studio. Решили это исправить и выбрали проект MTA. Multi Theft Auto (MTA) является модификацией для PC версий игры Grand Theft Auto: San Andreas от Rockstar North. MTA позволяет игрокам со всего мира играть друг против друга в режиме онлайн. Как написано в Wikipedia, особенностью игры является "оптимизированный код с наименьшим количеством сбоев". Что же, давайте посмотрим, что скажет анализатор кода.![]() Введение В этот раз, я решил не включать в статью диагностические сообщения, которые анализатор PVS-Studio выдаёт на подозрительные строки. Все равно я даю пояснения к фрагментам кода. Если интересно узнать, в какой именно строке найдена ошибка и какое диагностическое сообщение выдал анализатор, то это можно посмотреть в файле http://www.viva64.com/external-pictures/txt/mtasa-review.txt. Когда я просматривал проект, я выписывал в файл mtasa-review.txt фрагменты кода, которые мне показались подозрительными. Позже, основываясь на нём, я написал эту статью. Важно.В файл попали только те фрагменты код, которые не понравились лично мне. Я не участвую в разработке MTA и не представляю, как и что в ней работает. Поэтому, наверняка я местами ошибся: включил в список корректный код и пропустил настоящие ошибки. А где-то вообще поленился и не стал описывать не совсем правильный вызов функции printf(). Прошу разработчиков из MTA Team не полагаться на этот текст и самостоятельно проверить проект. Проект достаточно большой и демонстрационной версии не хватит для полноценной проверки. Однако мы http://www.viva64.com/ru/b/0193/ бесплатные open-source проекты. Напишите нам, и мы договоримся на тему бесплатной версии PVS-Studio. Итак, игра Multi Theft Auto является open-source проектом, написанным на языке Си/Си++:
Для проверки я использовал анализатор PVS-Studio 5.05:
Посмотрим теперь, что смог найти анализатор PVS-Studio в этой игре. Ошибок не так уж и много. Причём большинство из них содержится в редко используемых частях программы (обработчики ошибок). Это не удивительно. Большинство ошибок исправляется другими, более медленными и дорогими методами. Правильное использование статического анализа - регулярный запуск. Например, анализатор PVS-Studio умеет запускаться для только что изменённых и скомпилированных файлов (см. http://www.viva64.com/ru/d/0218/). Так разработчик сразу находит и устраняет многие ошибки и опечатки. Это во много раз быстрее и дешевле, чем обнаружить эти ошибки при тестировании. Подробнее эта тема рассматривалась в статье "http://www.viva64.com/ru/b/0105/". Хорошая статья. Рекомендую почитать вводную часть, чтобы понять идеологию использования таких инструментов, как PVS-Studio. Странные цвета
Случайно, вместо '&' используется '&&'. В результате от цвета остаются рожки и ножки в виде нуля или единицы. Идентичную беду можно наблюдать в файле "ccheckpointsa.cpp". Другая беда с цветопередачей.
Два раза копируется красный цвет, но не копируется синий. Правленый код, должен быть таким:
Идентичная проблема имеется в файле cdebugechopacket.h. Вообще, целый ряд ошибок в игре дублируется в двух файлах. Как мне кажется, один из файлов относится к клиентской части, а второй к серверной. Чувствуется вся мощь технологии Copy-Paste Что-то не так с utf8
Размер типа wchar_t в Windows составляет 2 байта. Диапазон его значений равен [0..65535]. Это значит, что сравнение с числами 0x10000, 0x200000, 0x4000000, 0x7fffffff не имеет смысла. Наверное, код должен был быть написан как-то иначе. Забытый break
В этом коде забыт оператор 'break'. В результате ситуация "BANNED_IP", обрабатывается так же, как и "BANNED_ACCOUNT". Странные проверки
Переменная два раза сравнивается с числом 1009. Чуть ниже можно найти ещё идентичное двойное сравнение. Следующее подозрительное сравнение:
Эта же ошибка скопирована в файл cclientsound.h. Разыменовывание нулевого указателя
Если не удалось создать объект "игрок", то программа пытается напечатать соответствующую информацию в консоль. Но не удачно. Плохая идея использовать нулевой указатель, вызывая функцию "pPlayer->GetSourceIP()". Другой нулевой указатель разыменовывается здесь:
Если указатель szCmdLine равен нулю, то произойдет его разыменование. Скорее всего, здесь должно быть так:
Больше всего, мне понравился вот этот фрагмент кода:
Красивый Copy-Paste.Вместо последней функции memcpy() должна вызываться функция memset(). Неочищенные массивы Есть целый ряд ошибок, связанный с неочищенными массивами. Ошибки можно разделить на две категории. Первая - не удалены элементы. Вторая - не во все элементы массива записаны нулевые значения. Неудалённые элементы
Функция empty() проверяет, содержит контейнер элементы или нет. Чтобы удалить элементы из контейнера 'm_TimingMap', следовало вызвать функцию clear(). Следующий пример:
Ещё несколько таких ошибок есть в файле cresource.cpp. Примечание. Если кто-то пропустил начало статьи и решил читать с середины: где находятся эта и остальные шибки, можно узнать в файле http://www.viva64.com/external-pictures/txt/mtasa-review.txt. Теперь об ошибках заполнения нулями
На первый взгляд всё хорошо. Вот только FillMemory() не будет иметь никакого эффекта. FillMemory() и memset() это не одно и тоже. Вот смотрите:
Второй и третий аргумент меняются местами. По этому, правильно будет так:
Аналогичная путаница существует в файле ccrashhandlerapi.cpp. И последний фрагмент кода на рассматриваемую тему. Здесь очищается только один байт.
Звездочка '*' является лишней. Должно быть написано "sizeof (m_buffer)". Неинициализированная переменная
Переменная 'base' используется для инициализации самой себя. Ещё одна такая ошибка есть несколькими строчками ниже. Выход за границу массива
Последняя строчка "m_DevInfo.axis[7].bEnabled = 0;" лишняя. Другая ошибка
И ещё одна:
Ещё, как минимум одна ошибка выхода за границы массива есть в файле cpoolssa.cpp. Но описывать её в статье я не стал. Получается длинноватый пример, а как сделать коротко и понятно, я не знаю. Эту и другие ошибки, как я уже говорил можно посмотреть в более полном отчёте. Пропущено слово 'throw'
Здесь должно было быть "throw InvalidRequestException(....)". Другой фрагмент кода.
Должно быть: throw std::length_error(....). Ой: free(new T[n])
Память выделяется с помощью оператора 'new'. А освободить её пытаются с помощью функции free(). Результат непредсказуем. Всегда истинные/ложные условия
Программист хотел проверить определенный бит в переменной Flag. Из-за опечатки, вместо операции '&' он использовал операцию '|'. В результате, условие всегда выполняется. Аналогичная путаница есть в файле cvehiclesa.cpp. Следующая ошибка с проверкой: unsigned_value < 0.
Функция Get() возвращает значение беззнакового типа 'unsigned long long'. Значит проверка "m_TidyupTimer.Get () < 0" не имеет смысла. Другие ошибки этой разновидности в встречаются в файлах: csettings.cpp, cmultiplayersa_1.3.cpp, cvehiclerpcs.cpp. Это может работать, но лучше провести рефакторинг Многие сообщения, выданные PVS-Studio, диагностируют ошибки, которые, скорее всего, никак не проявят себя. Я не люблю писать про такие ошибки. Это не интересно. Приведу только несколько примеров.
Третий аргумент функции strncat() указывает не размер буфера, а сколько ещё символов в него можно поместить. Теоретически, здесь возможно переполнение буфера. На практике, скорее всего это никогда не произойдёт. Подробнее про данный тип ошибки, можно почитать в описании диагностики http://www.viva64.com/ru/d/0263/. Ещё один пример.
Во многих местах игры используются функции CreateThread()/ExitThread(). Как правило, это не совсем верно. Следует использовать функции _beginthreadex()/_endthreadex(). Подробнее про это, можно узнать из описания диагностики http://www.viva64.com/ru/d/0102/. Надо где-то остановиться Я описал далеко не все из недочетов, которые я заметил. Однако, пора останавливаться. Статья уже и так достаточно велика. С другими ошибками, вы можете познакомиться в файле http://www.viva64.com/external-pictures/txt/mtasa-review.txt. Например, там есть следующие типы ошибок, отсутствующие в статье:
Заключение Анализатор PVS-Studio может эффективно быть использован для раннего устранения многих ошибок, как в игровых проектах, так и в любых других. Алгоритмические ошибки он не найдёт (для этого нужен искусственный интеллект). Зато существенно время, которое бесполезно тратится на поиск глупых ошибок и опечаток. Программисты тратят на простые дефекты гораздо больше, чем думают. Даже в уже отлаженном и оттестированном коде, http://www.viva64.com/ru/b/0203/. А при написании нового кода, таких ошибок исправляется в 10 раз больше. |
| Автор: EgoBrain 19.8.2013, 02:45 | ||||||||||||
| Странно, многие ошибки должны были быть замеченными на этапе написания, если разрабы конечно не в нодпаде++ каком-нибудь пишут. Например пропущенный break, студия тут же выдаст предупреждение. Ну или двойное сравнение
Разве не так? На многие ошибки посмотришь, и даже не верится что такое могли допустить опытные программисты задействованные в таком масштабном проекте
|
| Автор: bsa 19.8.2013, 13:42 |
| EgoBrain, и на старуху бывает проруха. |