Вышел новый релиз PVS-Studio — 7.24. В нём мы улучшили анализ проектов на Unity, добавили новые возможности работы с файлами подавления (*.suppress), реализовали ряд диагностик и сделали многое другое. Подробности в этой заметке.
Улучшения анализа проектов на Unity
Для многих классов игрового движка Unity оператор '==' перегружен особым образом. Наиболее интересной особенностью перегрузки является тот факт, что сравнение с null может вернуть true, даже если сравниваемая ссылка не является нулевой. Пример:
void Start()
{
GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Sphere);
Instantiate(obj);
if (obj == null)
Debug.Log("obj == null before destroy");
DestroyImmediate(obj);
if (obj == null)
Debug.Log("obj == null after destroy");
if (ReferenceEquals(obj, null))
Debug.Log("obj is really null");
if (obj is null)
Debug.Log("obj is really null 2");
}
Если вы работаете с Unity, то наверняка сможете сказать, что на экран консоли будет выведена единственная надпись: "obj == null after destroy". Всё потому, что оператор '==' при сравнении с null возвращает true, если сравниваемый объект уничтожен.
Новая версия анализатора лучше понимает такие особенности. В первую очередь это позволяет убрать ложные срабатывания о разыменовании нулевых ссылок. Также теперь PVS-Studio отслеживает обращения к методам и свойствам потенциально уничтоженных объектов. Такие обращения могут приводить к выбрасыванию исключений, и для их поиска мы добавили отдельное правило V3188.
Мы планируем и дальше улучшать возможности анализа проектов, использующих Unity, дорабатывая имеющиеся механизмы и реализуя новые диагностики. Обязательно пишите нам если у вас есть идеи по поводу того, какие ошибки анализатору стоит находить в таких проектах.
Продвинутые механизмы работы с файлами подавления в Visual Studio
В плагине для Visual Studio был расширен интерфейс для работы с файлами подавления (*.suppress). Раньше предполагалось, что в проекте может быть только один suppress-файл. Теперь же к каждому проекту может относиться несколько файлов подавления.
Ниже перечислены несколько нововведений.
1) Можно добавлять предупреждения в конкретные suppress-файлы:
2) Можно выбирать suppress-файлы, предупреждения из которых будут отображены в таблице:
3) Подавленные предупреждения можно также перемещать между suppress-файлами:
Эти возможности позволяют реализовывать новые сценарии работы с файлами подавления. К примеру, можно использовать один suppress-файл для предупреждений, оставленных "на потом", и ещё один — для ложных срабатываний.
Подробнее с этими и другими возможностями вы можете ознакомиться в документации.
Новые возможности подавления предупреждений из командной строки
В утилитах PVS-Studio_Cmd.exe и pvs-studio-dotnet появился новый режим — suppression. С помощью него можно производить различные операции с файлами подавления (*.suppress).
К примеру, можно создать для каждого проекта из решения новый suppress-файл:
PVS-Studio_Cmd.exe suppression -m CreateEmptySuppressFiles ^
-t JulietTestSuite.sln ^
-P myPrefix%projName%myPostfix.suppress
В результате выполнения такой команды в каждый проект решения будет добавлен пустой suppress-файл, имя которого генерируется на основе имени соответствующего проекта.
Ещё одной интересной возможностью является подавление предупреждений, соответствующих определённым критериям:
PVS-Studio_Cmd.exe suppression -m Suppress ^
-t JulietTestSuite.sln ^
-P myPrefix%projName%myPostfix.suppress ^
-R JulietTestSuite.plog ^
--groups "GA:3|OWASP"
Указанная команда подавит предупреждения из отчёта JulietTestSuite.plog в suppress-файлы, соответствующие паттерну, переданному через параметр '-P'. При этом подавлены будут только предупреждения 3 уровня группы General Analysis и все предупреждения группы OWASP.
Таким же образом можно и "снять подавление" с определённых предупреждений — для этого в качестве значения параметра '-m' необходимо передать 'UnSuppress'.
Эти и другие возможности нового режима подробно описаны в документации.
Учёт оператора null-forgiving ('!') в C#
В C# 9 в язык добавили возможность условного разделения ссылочных типов на допускающие и не допускающие null. Подробности — в официальной документации.
Когда ссылочная переменная может иметь значение null, к имени его типа добавляется '?'. Если же в конкретной ситуации такое выражение точно не возвращает нулевую ссылку, разработчики могут использовать оператор null-forgiving ('!'). Пример:
bool _returnText = false;
void Foo()
{
_returnText = true;
string value = GetText()!;
_ = value.Length;
}
// may return null
private string? GetText()
{
return _returnText ? "some text" : null;
}
Метод GetText в некоторых обстоятельствах действительно может возвращать null, однако результат его вызова внутри Foo точно является строкой "some text". Пометив вызов с помощью постфиксного '!', разработчик сообщает компилятору, что выражение не равно null.
Мы долго обдумывали необходимость учёта оператора null-forgiving при анализе. С одной стороны, он не даёт гарантий того, что выражение действительно не будет равно null. С другой — он является способом подавления ложных предупреждений компилятора о небезопасном разыменовании. Стоит ли ругаться там, где похожее предупреждение компилятора уже было подавлено?
В итоге анализатор всё же начал учитывать оператор null-forgiving при выдаче предупреждений. Теперь PVS-Studio не будет выдавать предупреждения о разыменовании потенциально нулевой ссылки, если выражение размечено с помощью '!'. Однако предупреждение всё же будет показано, если null является единственным возможным значением выражения.
Новые диагностики
C, C++
C#
Личный кабинет пользователя
Недавно мы добавили на сайт возможность создавать свой аккаунт и заходить в свой личный кабинет. Кнопки регистрации/авторизации можно найти в шапке сайта, наведя курсор на иконку:
Личный кабинет позволяет:
В общем, приглашаю всех регистрироваться :).
Подробнее о личном кабинете можете прочитать в заметке.
Статьи
Для тех, кто пишет на C++:
Для тех, кто пишет на C#:
Разное:
**
Загрузить актуальную версию PVS‑Studio можно здесь.
Если хотите получать пресс‑релизы по почте, подписывайтесь на рассылку.
0