Compartir a través de


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

Nombre de tipo

CallGCKeepAliveWhenUsingNativeResources

Identificador de comprobación

CA2115

Categoría

Microsoft.Security

Cambio problemático

No

Causa

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

Descripción de la regla

La recolección de elementos no utilizados finaliza un objeto si no hay ninguna referencia más a él en el código administrado. Las referencias no administradas a los objetos no evitan 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 IntPtr y el almacén de camposUIntPtr apuntan a los recursos no administrados. Puesto 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 de 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 esta infracción de la regla, agregue al método una llamada a KeepAlive, pasando una instancia actual (this en C# y C++) como el argumento. Coloque la llamada después de la última línea de código donde el objeto se debe proteger de la recolección de elementos no utilizados. Inmediatamente después de la llamada a KeepAlive, el objeto se considera de nuevo listo para la recolección de elementos no utilizados suponiendo que no hay ninguna referencia administrada a él.

Cuándo suprimir advertencias

Esta regla hace algunas suposiciones que pueden dar lugar a falsos positivos. Puede suprimir sin ningún riesgo una advertencia de esta regla si:

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

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

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

Ejemplo

En este ejemplo, BadMethod infringe la regla. GoodMethod contiene el código corregido.

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

   }

}

Vea también

Referencia

Implementar Finalize y Dispose para limpiar recursos no administrados

GC.KeepAlive

System.IntPtr

Object.Finalize

System.UIntPtr