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

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

** На сайте установлена reCAPTCHA и применяются
Политика конфиденциальности и Условия использования Google.
Ваше сообщение отправлено.

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


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

>
>
>
V3149. Dereferencing the result of 'as'…
Сообщения PVS-Studio
Диагностики общего назначения (General Analysis, C++)
Диагностики общего назначения (General Analysis, C#)
Диагностики общего назначения (General Analysis, Java)
Диагностика микро-оптимизаций (C++)
Диагностика 64-битных ошибок (Viva64, C++)
Cтандарт MISRA
Стандарт AUTOSAR
Дополнительная информация
Оглавление

V3149. Dereferencing the result of 'as' operator can lead to NullReferenceException.

4 декабря 2019 г.

Анализатор обнаружил небезопасное разыменование результата приведения типа через оператор 'as'.

Рассмотрим пример:

void Foo()
{
  BaseItem a = GetItem();
  var b = a as SpecificItem;
  b.Bar();
}

Возвращаемое методом значение может иметь тип, отличный от типа, к которому мы его приводим. Тогда при приведении типа с помощью оператора 'as' в переменную 'b' будет записано значение null. Хотя при самом приведении типа ошибки не будет, при последующем использовании этой переменной без проверки произойдёт выброс исключения 'NullReferenceException'. Исправленный код будет выглядеть так:

void Foo()
{
  BaseItem a = GetItem();
  var b = a as SpecificItem;
  b?.Bar();
}

Если вы уверены, что runtime тип значения у переменной, приводимой с помощью оператора 'as', всегда может быть успешно приведён к указанному типу, то лучше воспользоваться оператором явного приведения типа:

void Foo()
{
  BaseItem a = GetItem();
  var b = (SpecificItem)a;
  b.Bar();
}

В этом случае, если в будущем поведение программы поменяется и метод 'GetItem' перестанет всегда возвращать значение, гарантированно приводимое к заданному типу, в месте приведения будет сгенерировано исключение 'InvalidCastException', что позволит сразу идентифицировать проблемное место в коде. Напротив, используя оператор 'as' в такой ситуации, можно получить 'NullReferenceException' далее по коду, когда приведённая неуспешно переменная, содержащая null, будет разыменована. Причём это может произойти далеко от места, где производится приведение типов, например в другом методе, что затруднит локализацию и исправление такой ошибки.

Также диагностика указывает на возможные опечатки при проверках типа:

void Foo()
{
  IDisposable a = GetItem();
  if(a is NonSpecificItem)
  {
    var b = a as SpecificItem;
    b.Bar();
  }
}

В данном примере типы SpecificItem и NonSpecificItem не связаны друг с другом и результатом приведения будет нулевой указатель. Для защиты от таких опечаток можно использовать возможности C# 7.0 и сделать проверку через Is Type Pattern синтаксис:

void Foo()
{
  IDisposable a = GetItem();
  if(a is NonSpecificItem item)
  {
    item.Bar();
  }
}

Приведём пример работы диагностики на коде из открытого проекта:

....
FuelDefinition = MyDefinitionManager.Static.GetPhysicalItemDefinition(FuelId);
MyDebug.AssertDebug(FuelDefinition != null);
....
String constraintTooltip = FuelDefinition.DisplayNameText;

В данном примере метод 'GetPhysicalItemDefinition' возвращает объект типа MyPhysicalItemDefinition, полученный из массива объектов базового типа 'MyDefinitionBase':

public MyPhysicalItemDefinition GetPhysicalItemDefinition(MyDefinitionId id)
{
  ....
  return m_definitions.m_definitionsById[id] as MyPhysicalItemDefinition;
}

При этом после вызова метода 'GetPhysicalItemDefinition' присутствует проверка результата приведения на null (MyDebug.AssertDebug), что указывает на потенциальную возможность получения из метода объекта неподходящего типа. Однако данная проверка будет работать только в Debug версии приложения. В Release версии неудачное приведение приведёт к разыменованию нулевой ссылки далее по ходу выполнения программы (FuelDefinition.DisplayNameText).

Данная диагностика классифицируется как:

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