Share via


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

Articolo Valore
ID regola CA2115
Category Microsoft.Security
Modifica Nessuna interruzione

Causa

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

Nota

Questa regola è stata deprecata. Per altre informazioni, vedere Regole deprecate.

Descrizione regola

Garbage Collection finalizza un oggetto se non sono presenti altri riferimenti nel codice gestito. I riferimenti non gestiti agli oggetti non impediscono l'operazione di Garbage Collection. Questa regola rileva gli errori che possono verificarsi qualora una risorsa non gestita venga completata mentre è ancora usata da codice non gestito.

Questa regola presuppone che IntPtr e UIntPtr i campi archiviano puntatori a risorse non gestite. Poiché lo scopo di un finalizzatore è liberare risorse non gestite, la regola presuppone che il finalizzatore liberi la risorsa non gestita a cui puntano i campi del puntatore. Questa regola presuppone inoltre che il metodo faccia riferimento al campo del puntatore per passare la risorsa non gestita al codice non gestito.

Come correggere le violazioni

Per correggere una violazione di questa regola, aggiungere una chiamata al KeepAlive metodo , 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. Subito dopo la chiamata a KeepAlive, l'oggetto viene considerato di nuovo pronto per l'operazione di Garbage Collection presupponendo che non vi siano riferimenti gestiti.

Quando eliminare gli avvisi

Questa regola presuppone alcuni presupposti che possono portare a falsi positivi. È possibile eliminare in modo sicuro un avviso da questa regola se:

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

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

Esaminare attentamente altri messaggi prima di escluderli. Questa regola rileva errori difficili da riprodurre ed eseguire il debug.

Esempio

Nell'esempio BadMethod seguente non include una chiamata a GC.KeepAlive e pertanto viola la regola. GoodMethod contiene il codice corretto.

Nota

Questo esempio è pseudo-codice. Anche se il codice viene compilato ed eseguito, l'avviso non viene generato perché una risorsa non gestita non viene creata o liberata.

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

}

Vedi anche