Для получения триального ключа
заполните форму ниже
Team License (базовая версия)
Enterprise License (расширенная версия)
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Запросите информацию о ценах
Новая лицензия
Продление лицензии
--Выберите валюту--
USD
EUR
GBP
RUB
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Бесплатная лицензия PVS-Studio для специалистов Microsoft MVP
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Для получения лицензии для вашего открытого
проекта заполните, пожалуйста, эту форму
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Мне интересно попробовать плагин на:
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

Ваше сообщение отправлено.

Мы ответим вам на


Если вы так и не получили ответ, пожалуйста, проверьте папку
Spam/Junk и нажмите на письме кнопку "Не спам".
Так Вы не пропустите ответы от нашей команды.

>
>
>
Проверка проекта Dolphin-emu

Проверка проекта Dolphin-emu

24 Фев 2012

Нам регулярно предлагают проверить различные открытые проекты с помощью анализатора PVS-Studio. Если вы тоже хотите предложить что-то для проверки, то прошу перейти по этой ссылке. Очередным проектом стал проект Dolphin-emu.

Введение

Dolphin-emu это эмулятор Gamecube и Wii. Так как это проект с открытыми исходными кодами, любой может вносить улучшения. Код размещен на Github.

Мы нашли в этом проекте совсем мало ошибок. В первую очередь это связанно с тем, что это небольшой по объему проект. Размер проекта составляет около 260 000 строк кода. Оставшуюся часть проекта (1340 000 строк кода) составляют сторонние библиотеки, которые тестировать не так интересно.

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

Опечатки

Опечатки коварны и их можно встретить в любом приложении. Программисты уверены, что допускают только сложные ошибки и анализаторы в первую очередь должны искать утечки памяти и ошибки синхронизации. К сожалению, реальность намного банальнее и самыми распространенными ошибками являются опечатки и неправильно скопированные участки кода. Например, в Dolphin-emu есть такая функция:

bool IRBuilder::maskedValueIsZero(
  InstLoc Op1, InstLoc Op2) const
{
  return (~ComputeKnownZeroBits(Op1) &
          ~ComputeKnownZeroBits(Op1)) == 0;
}

Сообщение анализатора PVS-Studio:

V501 There are identical sub-expressions '~ComputeKnownZeroBits(Op1)' to the left and to the right of the '&' operator. Core ir.cpp 1215

Из-за опечатки два раза используется переменная 'Op1' и ни разу не используется 'Op2'. А вот другой пример, где не там поставлена закрывающаяся круглая скобка ')'.

static const char iplverPAL[0x100] = "(C) 1999-2001 ....";
static const char iplverNTSC[0x100]= "(C) 1999-2001 ....";
CEXIIPL::CEXIIPL() : ....
{
  ...
  memcpy(m_pIPL, m_bNTSC ? iplverNTSC : iplverPAL,
         sizeof(m_bNTSC ? iplverNTSC : iplverPAL));
  ...
}

Предупреждение PVS-Studio:

V568 It's odd that the argument of sizeof() operator is the 'm_bNTSC ? iplverNTSC : iplverPAL' expression. Core exi_deviceipl.cpp 112

Выражение внутри оператора sizeof() не вычисляется. Этот код работает только благодаря тому, что типы массивов 'iplverNTSC' и 'iplverPAL' совпадают. Получается, что sizeof() всегда возвращает 0x100. Это интересный момент. Если бы размер массива 'iplverNTSC' и 'iplverPAL ' отличался, то всё бы работало совсем по-другому. Рассмотрим тестовый пример для наглядности:

const char A[10] = "123";
const char B[10] = "123";
const char C[20] = "123";
cout << sizeof(true ? A : B) << ", "
     << sizeof(true ? A : C) << endl;

Результат работы программы: 10, 4.

В первом случае печатается размер массива, а во втором - размер указателя.

Ошибки низкоуровневой работы с памяти

Помимо опечаток очень часто встречаются ошибки работы с такими функциями как memset() и memcpy().

u32 Flatten(..., BlockStats *st, ...)
{
  ...
  memset(st, 0, sizeof(st));
  ...
}

Предупреждение PVS-Studio:

V579 The memset function receives the pointer and its size as arguments. It is possibly a mistake. Inspect the third argument. Core ppcanalyst.cpp 302

Случайно вычисляется размер указателя на объект, а не размер самого объекта BlockStats. Правильный вариант: sizeof(*st).

А вот другая аналогичная ситуация:

void drawShadedTexSubQuad(...,
  const MathUtil::Rectangle<float>* rDest, ...)
{
  ...
  if (stsq_observer ||
      memcmp(rDest,
        &tex_sub_quad_data.rdest, sizeof(rDest)) != 0 ||
      tex_sub_quad_data.u1 != u1 ||
      tex_sub_quad_data.v1 != v1 ||
      tex_sub_quad_data.u2 != u2 ||
      tex_sub_quad_data.v2 != v2 ||
      tex_sub_quad_data.G != G)
  ...
}

Сравнивается только часть структуры. Правильный вариант: sizeof(*rDest).

Работа с float

В некоторых местах проекта Dolphin-emu, работа с переменными типа float, выглядит излишне оптимистично. Переменные типа float сравниваются с помощью операторов == и !=. Подобные сравнения допустимы только в определенных случаях. Более подробно о сравнении переменных типа float можно познакомиться в документации к диагностическому правилу V550. Рассмотрим пример:

float Slope::GetValue(float dx, float dy)
{
  return f0 + (dfdx * dx) + (dfdy * dy);
}

void BuildBlock(s32 blockX, s32 blockY)
{
  ...
  float invW = 1.0f / WSlope.GetValue(dx, dy);
  ...
  float q = TexSlopes[i][2].GetValue(dx, dy) * invW;
  if (q != 0.0f)
    projection = invW / q;
  ...
}

Предупреждение PVS-Studio

V550 An odd precise comparison: q != 0.0f. It's probably better to use a comparison with defined precision: fabs(A - B) > Epsilon. VideoSoftware rasterizer.cpp 264

Обратите внимание на сравнение "if (q != 0.0f)". Как видно из кода, переменная 'q' вычисляется достаточно сложным образом. И как следствие, практически невероятно, что она ТОЧНО будет равна нулю. Скорее всего, переменная может получить, например значение 0.00000002. Это не 0, но деление на такое маленькое число может привести к переполнению. Необходима специальная проверка на подобные случаи.

Насилие над строками

void CMemoryWindow::onSearch(wxCommandEvent& event)
{
  ...
  //sprintf(tmpstr, "%s%s", tmpstr, rawData.c_str());
  //strcpy(&tmpstr[1], rawData.ToAscii());
  //memcpy(&tmpstr[1], &rawData.c_str()[0], rawData.size());
  sprintf(tmpstr, "%s%s", tmpstr, (const char *)rawData.mb_str());
  ...
}

Из закомментированного кода видно, что это больное место. Это уже четвертая попытка сформировать строку. К сожалению, она тоже далека от идеала. Анализатор PVS-Studio предупреждает:

V541 It is dangerous to print the string 'tmpstr' into itself. Dolphin memorywindow.cpp 344

Опасность заключается в том, что строка "tmpstr" печатается в саму себя. Этот код может корректно работать, но так лучше не делать. В зависимости от реализации функции sprintf() можно неожиданно получить некорректный результат. Возможно, здесь более уместно было бы использовать функцию strcat().

Есть и другие участки кода, которые хотя и работают, но весьма потенциально опасны:

V541 It is dangerous to print the string 'pathData_bin' into itself. Dolphin wiisavecrypted.cpp 513

V541 It is dangerous to print the string 'regs' into itself. Core interpreter.cpp 84

V541 It is dangerous to print the string 'fregs' into itself. Core interpreter.cpp 89

Заключение

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

Популярные статьи по теме
Зло живёт в функциях сравнения

Дата: 19 Май 2017

Автор: Андрей Карпов

Возможно, читатели помнят мою статью под названием "Эффект последней строки". В ней идёт речь о замеченной мной закономерности: ошибка чаще всего допускается в последней строке однотипных блоков текс…
Как PVS-Studio оказался внимательнее, чем три с половиной программиста

Дата: 22 Окт 2018

Автор: Андрей Карпов

PVS-Studio, как и другие статические анализаторы кода, часто выдаёт ложные срабатывания. Но не стоит спешить считать странные срабатывания ложными. Это короткая история о том, как PVS-Studio вновь ок…
Любите статический анализ кода!

Дата: 16 Окт 2017

Автор: Андрей Карпов

Я в шоке от возможностей статического анализа кода, хотя сам участвую в разработке инструмента PVS-Studio. На днях я был искренне удивлён тому, что анализатор оказался умнее и внимательнее меня.
PVS-Studio для Java

Дата: 17 Янв 2019

Автор: Андрей Карпов

В седьмой версии статического анализатора PVS-Studio мы добавили поддержку языка Java. Пришло время немного рассказать, как мы начинали делать поддержку языка Java, что у нас получилось и какие дальн…
Статический анализ как часть процесса разработки Unreal Engine

Дата: 27 Июн 2017

Автор: Андрей Карпов

Проект Unreal Engine развивается - добавляется новый код и изменятся уже написанный. Неизбежное следствие развития проекта - появление в коде новых ошибок, которые желательно выявлять как можно раньш…
Главный вопрос программирования, рефакторинга и всего такого

Дата: 14 Апр 2016

Автор: Андрей Карпов

Вы угадали, ответ - "42". Здесь приводится 42 рекомендации по программированию, которые помогут избежать множества ошибок, сэкономить время и нервы. Автором рекомендаций выступает Андрей Карпов - тех…
Эффект последней строки

Дата: 31 Май 2014

Автор: Андрей Карпов

Я изучил множество ошибок, возникающих в результате копирования кода. И утверждаю, что чаще всего ошибки допускают в последнем фрагменте однотипного кода. Ранее я не встречал в книгах описания этого …
Характеристики анализатора PVS-Studio на примере EFL Core Libraries, 10-15% ложных срабатываний

Дата: 31 Июл 2017

Автор: Андрей Карпов

После большой статьи про проверку операционной системы Tizen мне было задано много вопросов о проценте ложных срабатываний и о плотности ошибок (сколько ошибок PVS-Studio выявляет на 1000 строк кода)…
Бесплатный PVS-Studio для тех, кто развивает открытые проекты

Дата: 22 Дек 2018

Автор: Андрей Карпов

В канун празднования нового 2019 года команда PVS-Studio решила сделать приятный подарок всем контрибьюторам open-source проектов, хостящихся на GitHub, GitLab или Bitbucket. Им предоставляется возмо…
Как и почему статические анализаторы борются с ложными срабатываниями

Дата: 20 Мар 2017

Автор: Андрей Карпов

В своей предыдущей статье я писал, что мне не нравится подход, при котором статические анализаторы кода оцениваются с помощью синтетических тестов. В статье приводился пример, воспринимаемый анализат…

Комментарии (0)

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