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

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

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

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

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

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

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


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

>
>
Как же программа работает со всеми этим…

Как же программа работает со всеми этими ошибками?

27 Июн 2015

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

0336_How_Do_Programs_Run_with_All_Those_Bugs_At_All_ru/image1.png

Введение

Пара вводных слов для читателей, ещё не знакомых с нашим инструментом. Мы разрабатываем анализатор PVS-Studio для нахождения ошибок в исходном коде приложений, написанных на C/C++. Самый лучший способ показать, что он умеет, это проверять открытые проекты и находить в них ошибки. Найденные ошибки мы собираем в базу. Если в проекте мы находим интересные на наш взгляд ошибки, то пишем статью. Всем желающим предлагаю взглянуть на обновляемый список статей.

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

Самое важное

Различные фрагменты кода выполняются с разной частотой. Некоторые участки кода выполняются при каждом запуске программы, некоторые - от случая к случаю, есть участки, которые выполняются крайне редко.

Чем реже участок кода выполняется, тем легче в нем спрятаться ошибке. Попробую пояснить это на примерах.

Если из-за ошибки не рисуется большая кнопка в главном окне программы, то эту ошибку сразу заметят. Причем скорее всего ошибку исправит сам программист и она даже не доберётся до отдела тестирования.

Если ошибка зависит от входных данных, то ей уже легче спрятаться. Представим, что программист разрабатывает графический редактор. Он протестировал работу приложения на картинках с разрешением 100x100 и 300x400. И хотя он написал плохой код, у него всё работало. К счастью в компании есть отдел тестирования, в котором заметили, что программа не работает с вытянутыми картинками разрешением 100x10000. Обратите внимание, что ошибка прожила немного дольше.

Более скрытны ошибки, для возникновения которых нужны особые условия. Наш графический редактор отлично работает с картинками среднего и большого размера. Но представим, что картинку 1x1 надо обрабатывать особым образом, а ни программист, ни тестеры не подумали проверить такой режим работы. В результате программа упадёт у пользователя, который случайно создаст картинку размером в 1 пиксель. В этот раз ошибка добралась до пользователя.

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

Ответ на вопрос

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

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

QV4::ReturnedValue
QQuickJSContext2DPrototype::method_getImageData(....)
{
  ....
  qreal x = ctx->callData->args[0].toNumber();
  qreal y = ctx->callData->args[1].toNumber();
  qreal w = ctx->callData->args[2].toNumber();
  qreal h = ctx->callData->args[3].toNumber();
  if (!qIsFinite(x) || !qIsFinite(y) ||
      !qIsFinite(w) || !qIsFinite(w))
  ....
}

Функция содержит ошибку. Не проверяется значение 'h'. Вместо этого дважды проверяется переменная 'w'. Это ошибка? Да, это ошибка. Но вероятность, что она проявит себя весьма мала.

Во-первых, не во всех приложениях, использующих библиотеку Qt, будет вызывается функция method_getImageData(). Скорее всего её вообще мало кто использует. Во-вторых, ошибка проявит себя только если будет неправильно конвертирован последний аргумент. Все остальные аргументы обрабатываются правильно. В-третьих, этот последний аргумент должен оказаться некорректно заданным. Таким образом вероятность что эта ошибка проявится себя очень мала.

И поэтому она прожила в коде библиотеки Qt долгое время, прежде чем была обнаружена с помощью PVS-Studio. Кстати, если кто-то хочет прочитать подробнее о проверке библиотеки, то предлагаю взглянуть на нашу статью "Проверка фреймворка Qt 5".

Подведём итог.

Программы в процессе разработки и сопровождения тестируются различными методиками (юнит-тесты, регрессионные тесты, ручные тесты и так далее). Явные ошибки быстро устраняются, так как на них часто наталкиваются как сами разработчики, так и пользователи их продукта.

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

То есть ошибки есть. Их даже много (проверка N1, N2, N3, N4). Но, запуская Chromium, вы вряд ли с ними столкнётесь. Нужно будет приложить усилие и, возможно, очень большое, чтобы суметь попасть в ветвь кода, содержащую ошибку.

PVS-Studio не нужен?

Дочитав до этого места можно поторопиться и сделать ошибочный вывод: "Раз PVS-Studio не нужен, раз находится несущественные, никак не проявляющие себя ошибки".

Обычно, когда я чувствую, что можно сделать такой вывод, я отправляю читателя познакомиться со статьей "Лев Толстой и статический анализ кода". Но сейчас я ещё раз постараюсь сформулировать ответ другим словами.

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

Самое плохое, что можно делать, это прогонять анализатор незадолго до релиза. В этом нет никакого прока. Огромное количество ошибок, которые мог бы найти анализатор, к этому моменту будут исправлены ценой пота и крови. Эти неэффективно (пример, как зря потратить 50 часов времени). А потом после бессонных ночей в отладчике, переписываний с тестерами, разработчики запускают анализатор и получают всего пару полезных сообщений. Ведь всё самое страшное они исправили самостоятельно, потратив массу времени и сил. Зачем? Это какой-то Epic Fail.

При этом я не сгущаю краски. Разработчик действительно часто не понимают, как использовать анализаторы кода. Нередко в письмах мы видим приблизительно следующее: "Прикольная штука. Будем использовать её перед релизами". Это печально. Поэтому я вновь и вновь несу свет в царство темных багов и программистов, не желающих думать.

Я не говорю, что анализатор может найти все ошибки. Он найдет только часть. Но зато сделает это сразу. Как только программист закончит писать очередной фрагмент кода.

Идея статического анализа в том, что многие ошибки и опечатки можно найти на самом раннем этапе. Используйте его регулярно, и вы существенно сократите время, которое тратите на поиск и устранение дефектов.

PVS-Studio нужен!

Чтобы окончательно вас убедить, я приведу один практический пример. Недавно мы проверяли и исправляли все ошибки в игровом движке Unreal Engine. Большинство ошибок было некритичными. Это естественно. Было бы много критичных ошибок, никто бы не стал использовать Unreal Engine в своих разработках.

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

static void GetArrayOfSpeakers(....)
{
  Speakers.Reset();
  uint32 ChanCount = 0;
  // Build a flag field of the speaker outputs of this device
  for (uint32 SpeakerTypeIndex = 0;
       SpeakerTypeIndex < ESpeaker::SPEAKER_TYPE_COUNT,    // <=
       ChanCount < NumChannels; ++SpeakerTypeIndex)
  {
    ....
  }
  check(ChanCount == NumChannels);
}

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

Желающим поподробнее узнать историю нашей работы с компанией Epic Games предлагаю познакомиться со статьёй "Как команда PVS-Studio улучшила код Unreal Engine".

Заключение

Предлагаю не откладывать и попробовать наш анализатор кода PVS-Studio на своём проекте. Вы можете скачать его здесь. Интерфейс анализатора весьма прост, но предлагаю взглянуть на статью "PVS-Studio для Visual C++". Возможно, вы почерпнете для себя полезные советы по использованию анализатора. Например, многие не догадываются как легко и быстро можно исключить из результатов анализа сторонние библиотеки.

Если вы используете для сборки makefile или свою собственную сборочную систему, то проверить проект вам поможет PVS-Studio Standalone. В этом инструменте имеется механизм отслеживания запусков компилятора.

Если вас пугает количество предупреждений, то попробуйте новый режим разметки сообщений, использующий специальную базу. Идея: все сообщения считаются не интересными и не отображаются. Вы видите только сообщения, относящиеся к новому коду. Вы быстро поймете, как полезен и удобен регулярный анализ кода. Подробности: "Как внедрить статический анализ в проект".

Желаю удачи!

Популярные статьи по теме
Как увеличилась производительность LINQ в .NET 7?

Дата: 30 Ноя 2022

Автор: Михаил Евтихевич

В новой версии .NET улучшилась производительность методов Min, Max, Average и Sum для массивов и списков. Как вы думаете, во сколько раз увеличилась скорость их выполнения? В 2 раза, в 5? Нет, они ст…
Что такое катастрофический возврат и как регулярное выражение может стать причиной ReDoS-уязвимости?

Дата: 03 Ноя 2022

Автор: Андрей Москалёв

Регулярные выражения – очень полезный и удобный инструмент для поиска и замены текста. Однако в некоторых случаях они могут привести к зависанию системы или даже стать причиной уязвимости к ReDoS-ата…
Обзор нововведений в C# 11

Дата: 21 Окт 2022

Автор: Константин Волоховский

C# 11 выходит уже совсем скоро, так что пора детально изучить новые особенности, которые появятся в языке. И хотя их немного, среди них есть довольно интересные: обобщённая математика, исходные строк…
Есть ли жизнь без RTTI: пишем свой dynamic_cast

Дата: 13 Окт 2022

Автор: Владислав Столяров

В современном С++ осталось не так много вещей, которые не подходят под парадигму "Не плати за то, что не используешь". Одна из них – dynamic_cast. В рамках данной статьи мы разберёмся, что с ним не т…
Особенности реализации List в C#

Дата: 04 Окт 2022

Автор: Артём Ровенский

List является одной из самых популярных коллекций в C#. Давайте разберёмся в некоторых особенностях работы с ним и посмотрим на внутреннюю реализацию его отдельных частей.

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

Следующие комментарии
Unicorn with delicious cookie
Мы используем куки, чтобы пользоваться сайтом было удобно.
Хорошо