![]() |
Модераторы: bsa |
![]() ![]() ![]() |
|
Thunderbolt |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
![]() DevRel ![]() Профиль Группа: Участник Сообщений: 122 Регистрация: 7.11.2007 Где: Тула Репутация: 6 Всего: 16 |
Мы давно не проверяли игры с помощью PVS-Studio. Решили это исправить и выбрали проект MTA. Multi Theft Auto (MTA) является модификацией для PC версий игры Grand Theft Auto: San Andreas от Rockstar North. MTA позволяет игрокам со всего мира играть друг против друга в режиме онлайн. Как написано в Wikipedia, особенностью игры является "оптимизированный код с наименьшим количеством сбоев". Что же, давайте посмотрим, что скажет анализатор кода.
![]() Введение В этот раз, я решил не включать в статью диагностические сообщения, которые анализатор PVS-Studio выдаёт на подозрительные строки. Все равно я даю пояснения к фрагментам кода. Если интересно узнать, в какой именно строке найдена ошибка и какое диагностическое сообщение выдал анализатор, то это можно посмотреть в файле mtasa-review.txt. Когда я просматривал проект, я выписывал в файл mtasa-review.txt фрагменты кода, которые мне показались подозрительными. Позже, основываясь на нём, я написал эту статью. Важно.В файл попали только те фрагменты код, которые не понравились лично мне. Я не участвую в разработке MTA и не представляю, как и что в ней работает. Поэтому, наверняка я местами ошибся: включил в список корректный код и пропустил настоящие ошибки. А где-то вообще поленился и не стал описывать не совсем правильный вызов функции printf(). Прошу разработчиков из MTA Team не полагаться на этот текст и самостоятельно проверить проект. Проект достаточно большой и демонстрационной версии не хватит для полноценной проверки. Однако мы поддерживаем бесплатные open-source проекты. Напишите нам, и мы договоримся на тему бесплатной версии PVS-Studio. Итак, игра Multi Theft Auto является open-source проектом, написанным на языке Си/Си++: Для проверки я использовал анализатор PVS-Studio 5.05:
Посмотрим теперь, что смог найти анализатор PVS-Studio в этой игре. Ошибок не так уж и много. Причём большинство из них содержится в редко используемых частях программы (обработчики ошибок). Это не удивительно. Большинство ошибок исправляется другими, более медленными и дорогими методами. Правильное использование статического анализа - регулярный запуск. Например, анализатор PVS-Studio умеет запускаться для только что изменённых и скомпилированных файлов (см. режим инкрементального анализа). Так разработчик сразу находит и устраняет многие ошибки и опечатки. Это во много раз быстрее и дешевле, чем обнаружить эти ошибки при тестировании. Подробнее эта тема рассматривалась в статье "Лев Толстой и статический анализ кода". Хорошая статья. Рекомендую почитать вводную часть, чтобы понять идеологию использования таких инструментов, как 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. Примечание. Если кто-то пропустил начало статьи и решил читать с середины: где находятся эта и остальные шибки, можно узнать в файле 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() указывает не размер буфера, а сколько ещё символов в него можно поместить. Теоретически, здесь возможно переполнение буфера. На практике, скорее всего это никогда не произойдёт. Подробнее про данный тип ошибки, можно почитать в описании диагностики V645. Ещё один пример.
Во многих местах игры используются функции CreateThread()/ExitThread(). Как правило, это не совсем верно. Следует использовать функции _beginthreadex()/_endthreadex(). Подробнее про это, можно узнать из описания диагностики V513. Надо где-то остановиться Я описал далеко не все из недочетов, которые я заметил. Однако, пора останавливаться. Статья уже и так достаточно велика. С другими ошибками, вы можете познакомиться в файле mtasa-review.txt. Например, там есть следующие типы ошибок, отсутствующие в статье:
Заключение Анализатор PVS-Studio может эффективно быть использован для раннего устранения многих ошибок, как в игровых проектах, так и в любых других. Алгоритмические ошибки он не найдёт (для этого нужен искусственный интеллект). Зато существенно время, которое бесполезно тратится на поиск глупых ошибок и опечаток. Программисты тратят на простые дефекты гораздо больше, чем думают. Даже в уже отлаженном и оттестированном коде, таких ошибок много. А при написании нового кода, таких ошибок исправляется в 10 раз больше. --------------------
Карпов Андрей, DevRel в PVS-Studio. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
EgoBrain |
|
||||||||||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 537 Регистрация: 23.3.2008 Где: Комната Репутация: нет Всего: 2 |
Странно, многие ошибки должны были быть замеченными на этапе написания, если разрабы конечно не в нодпаде++ каком-нибудь пишут.
Например пропущенный break, студия тут же выдаст предупреждение. Ну или двойное сравнение
Разве не так? На многие ошибки посмотришь, и даже не верится что такое могли допустить опытные программисты задействованные в таком масштабном проекте
|
||||||||||||
|
|||||||||||||
bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 85 Всего: 196 |
EgoBrain, и на старуху бывает проруха.
![]() |
|||
|
||||
![]() ![]() ![]() |
Правила форума "C/C++: Для новичков" | |
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa. |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Для новичков | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |