>
>
>
V3145. Unsafe dereference of a WeakRefe…


V3145. Unsafe dereference of a WeakReference target. The object could have been garbage collected before the 'Target' property was accessed.

Анализатор обнаружил небезопасное использование объекта типа 'WeakReference', которое может привести к разыменованию нулевой ссылки.

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

string Foo(WeakReference weak)
{
    return weak.Target.ToString();
}

Так как объект, на который 'WeakReference' хранит ссылку, может быть в любой момент очищен сборщиком мусора, всегда существует вероятность, что свойство 'Target' вернёт значение 'null'.

В таком случае, при попытке вызова метода 'ToString' может произойти разыменование нулевой ссылки и будет выброшено исключение 'NullReferenceException'. Один из вариантов защиты от потенциального удаления объекта – запись его в локальную переменную, на время работы с ним. Исправленный код будет выглядеть так:

string Foo(WeakReference weak)
{
    var weakTarget = weak.Target;
    return weakTarget != null ? weakTarget.ToString() : String.Empty;
}

После записи ссылки в локальную переменную, сборщик мусора уже не сможет удалить этот объект, пока ссылка на него находится на стеке. Тем не менее, после записи объекта в локальную переменную её обязательно нужно проверить на 'null', т.к. в момент доступа к свойству 'Target' объект, на который 'Target' указывал, уже мог быть удалён сборщиком мусора.

Проверка на существование объекта внутри 'WeakReference' с помощью свойства 'IsAlive' также не защитит от возникновения 'NullReferenceException', так как между проверкой 'IsAlive' и разыменованием свойства 'Target' объект также может быть удалён сборщиком мусора:

char Foo(WeakReference weak)
{
  if (weak.IsAlive)
     return (weak.Target as String)[0];
  return ' ';
}

Корректное использование свойства 'IsAlive' может выглядеть так:

char Foo(WeakReference weak)
{
  var str = weak.Target as String;
  if (weak.IsAlive)
     return str[0];

  return ' ';
}

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

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