Condividi tramite


CA2115: Chiamare GC.KeepAlive durante l'utilizzo di risorse native

TypeName

CallGCKeepAliveWhenUsingNativeResources

CheckId

CA2115

Category

Microsoft.Security

Breaking Change

Non sostanziale

Causa

Un metodo dichiarato in un tipo con un finalizzatore fa riferimento a un campo System.IntPtr o System.UIntPtr, ma non chiama GC.KeepAlive.

Descrizione della regola

Garbage Collection completa un oggetto se nel codice gestito non sono presenti ulteriori riferimenti a esso. I riferimenti non gestiti agli oggetti non impediscono Garbage Collection. Questa regola rileva gli errori che possono verificarsi qualora una risorsa non gestita venga completata mentre è ancora utilizzata da codice non gestito.

Questa regola presuppone che nei campi IntPtr e UIntPtr siano archiviati puntatori a risorse non gestite. Poiché lo scopo di un finalizzatore consiste nel liberare risorse non gestite, la regola presuppone che il finalizzatore liberi le risorse non gestite indicate dai campi del puntatore. Questa regola presuppone inoltre che il metodo faccia riferimento al campo del puntatore per passare la risorsa non gestita a codice non gestito.

Come correggere le violazioni

Per correggere una violazione di questa regola, aggiungere al metodo una chiamata a KeepAlive, passando l'istanza corrente (this in C# e C++) come argomento. Posizionare la chiamata dopo l'ultima riga di codice in cui l'oggetto deve essere protetto da Garbage Collection. Immediatamente dopo la chiamata a KeepAlive, l'oggetto viene nuovamente considerato pronto per Garbage Collection, presupponendo che non siano presenti riferimenti gestiti a esso.

Esclusione di avvisi

Questa regola si basa su alcune presupposizioni che possono portare a falsi positivi. L'esclusione di un avviso da questa regola è sicura nei seguenti casi:

  • Il finalizzatore non libera il contenuto del campo IntPtr o UIntPtr a cui il metodo fa riferimento.

  • Il metodo non passa il campo IntPtr o UIntPtr a codice non gestito.

Rivedere accuratamente gli altri messaggi prima di escluderli. Questa regola rileva errori difficili da riprodurre e da sottoporre a debug.

Esempio

Nell'esempio riportato di seguito, BadMethod viola la regola. GoodMethod contiene il codice corretto.

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

   }

}

Vedere anche

Riferimenti

Implementazione dei metodi Finalize e Dispose per la pulizia delle risorse non gestite

GC.KeepAlive

System.IntPtr

Object.Finalize

System.UIntPtr