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