Share via


CA2115: Llamar a Call GC.KeepAlive cuando se utilicen recursos nativos

Elemento Valor
RuleId CA2115
Category Microsoft.Security
Cambio importante Poco problemático

Causa

Un método declarado en un tipo con un finalizador hace referencia a un campo System.IntPtr o System.UIntPtr, pero no llama a System.GC.KeepAlive.

Nota

Esta regla está en desuso. Para más información, consulte Reglas en desuso.

Descripción de la regla

La recolección de elementos no utilizados finaliza un objeto si no hay más referencias a él en el código administrado. Las referencias no administradas a objetos no impiden la recolección de elementos no utilizados. Esta regla detecta errores que pueden haberse producido porque se finaliza un recurso no administrado mientras todavía se utiliza en código no administrado.

Esta regla supone que los campos IntPtr y UIntPtr almacenan punteros a recursos no administrados. Dado que el propósito de un finalizador es liberar recursos no administrados, la regla supone que el finalizador liberará el recurso no administrado al que apuntan los campos del puntero. Esta regla también supone que el método hace referencia al campo de puntero para pasar el recurso no administrado al código no administrado.

Cómo corregir infracciones

Para corregir una infracción de esta regla, agregue una llamada al método KeepAlive y pase la instancia actual (this en C# y C++) como argumento. Coloque la llamada después de la última línea de código en la que el objeto deba protegerse de la recolección de elementos no utilizados. Inmediatamente después de la llamada a KeepAlive, el objeto se vuelve a considerar listo para la recolección de elementos no utilizados suponiendo que no haya referencias administradas a él.

Cuándo suprimir las advertencias

Esta regla realiza algunas suposiciones que pueden dar lugar a falsos positivos. Se puede suprimir una advertencia de esta regla si:

  • El finalizador no libera el contenido del campo IntPtr o UIntPtr al que hace referencia el método.

  • El método no pasa el campo IntPtr o UIntPtr al código no administrado.

Revise cuidadosamente otros mensajes antes de excluirlos. Esta regla detecta errores difíciles de reproducir y depurar.

Ejemplo

En el ejemplo siguiente, BadMethod no incluye una llamada a GC.KeepAlive y, por lo tanto, infringe la regla. GoodMethod contiene el código corregido.

Nota

Este ejemplo es pseudocódigo. Aunque el código se compila y se ejecuta, la advertencia no se desencadena porque no se crea ni libera ningún recurso no administrado.

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 ...
      }
      
   }

}

Consulte también