Поделиться через


CA2115: вызывайте GC.KeepAlive при использовании собственных ресурсов

Товар Значение
Идентификатор правила CA2115
Категория Microsoft.Security
Критическое изменение Не критическое

Причина

Метод, объявленный в типе с методом завершения, ссылается на System.IntPtr поле или System.UIntPtr не вызывает System.GC.KeepAlive.

Примечание.

Это правило устарело. Дополнительные сведения см. в разделе "Устаревшие правила".

Описание правила

Сборка мусора завершает объект, если в управляемом коде нет дополнительных ссылок. Неуправляемые ссылки на объекты не препятствуют сборке мусора. Данное правило обнаруживает ошибки, которые могут возникать из-за завершения неуправляемых ресурсов, по-прежнему используемых в машинном коде.

Это правило предполагает, что IntPtr и UIntPtr поля хранят указатели на неуправляемые ресурсы. Поскольку цель средства завершения — освободить неуправляемые ресурсы, правило предполагает, что средство завершения освободит неуправляемый ресурс, на который указывает поля указателя. Это правило также предполагает, что метод ссылается на поле указателя для передачи неуправляемого ресурса неуправляемого кода.

Устранение нарушений

Чтобы устранить нарушение этого правила, добавьте вызов KeepAlive метода, передав текущий экземпляр (this в C# и C++) в качестве аргумента. Поместите вызов после последней строки кода, в которой объект должен быть защищен от сборки мусора. Сразу после вызова KeepAliveобъект снова считается готовым к сборке мусора, если к нему нет управляемых ссылок.

Когда лучше отключить предупреждения

Это правило делает некоторые предположения, которые могут привести к ложным срабатываниям. Вы можете безопасно отключить предупреждение из этого правила, если:

  • Средство завершения не освобождает содержимое IntPtr поля, UIntPtr на который ссылается метод.

  • Метод не передает поле в UIntPtr неуправляемый IntPtr код.

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

Пример

В следующем примере BadMethod не включает вызов GC.KeepAlive и поэтому нарушает правило. GoodMethod содержит исправленный код.

Примечание.

В этом примере используется псевдокод. Хотя код компилируется и выполняется, предупреждение не запускается, так как неуправляемый ресурс не создается или не освобождается.

using System;

namespace SecurityRulesLibrary
{
   class IntPtrFieldsAndFinalizeRequireGCKeepAlive
   {
      private IntPtr unmanagedResource;
      
      IntPtrFieldsAndFinalizeRequireGCKeepAlive()
      {
         GetUnmanagedResource (unmanagedResource);
      }

      // The finalizer frees the unmanaged resource.
      ~IntPtrFieldsAndFinalizeRequireGCKeepAlive()
      {
         FreeUnmanagedResource (unmanagedResource);
      }

      // Violates rule:CallGCKeepAliveWhenUsingNativeResources. 
      void BadMethod()
      {
         // Call some unmanaged code.
         CallUnmanagedCode(unmanagedResource);
      }

      // Satisfies the rule.
      void GoodMethod()
      {
         // Call some unmanaged code.
         CallUnmanagedCode(unmanagedResource);
         GC.KeepAlive(this);
      }

      // Methods that would typically make calls to unmanaged code.
      void GetUnmanagedResource(IntPtr p)
      {
        // Allocate the resource ...
      }
      void FreeUnmanagedResource(IntPtr p)
      {
        // Free the resource and set the pointer to null ...
      }
      void CallUnmanagedCode(IntPtr p)
      {
        // Use the resource in unmanaged code ...
      }
      
   }

}

См. также