# 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 ' ';
    }

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

CWE-476

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