Questo articolo è stato tradotto automaticamente. Per visualizzare l'articolo in inglese, selezionare la casella di controllo Inglese. È possibile anche visualizzare il testo inglese in una finestra popup posizionando il puntatore del mouse sopra il testo.
Traduzione
Inglese

Handle protetti e finalizzazione critica

Nelle versioni di .NET Framework precedenti alla 2.0 tutti gli handle del sistema operativo possono essere incapsulati solo nell'oggetto wrapper gestito IntPtr. Benché in questo modo sia possibile interagire agevolmente con il codice nativo, esiste il rischio di perdita degli handle per le eccezioni asincrone, ad esempio un thread che si interrompe in modo imprevisto o un overflow dello stack. Queste eccezioni asincrone rappresentano un ostacolo per la pulizia delle risorse del sistema operativo e possono verificarsi praticamente ovunque nel programma. Nella maggior parte dei casi si verificano in applicazioni in cui viene utilizzato un host che esegue codice gestito, ad esempio Microsoft SQL Server.

In alcune circostanze gli oggetti finalizzabili possono essere recuperati dalla Garbage Collection durante l'esecuzione di un metodo nell'ambito di un chiamata pInvoke. Se un finalizzatore libera l'handle passato alla chiamata pInvoke, è possibile che l'handle venga danneggiato. L'handle può anche essere recuperato mentre il metodo è bloccato durante una chiamata pInvoke, ad esempio durante la lettura di un file.

Ancora più importante, poiché gli handle vengono riciclati frequentemente in Windows, è possibile che un handle venga riciclato e punti a un'altra risorsa contenente dati sensibili. Questo comportamento è noto come attacco basato sul riciclaggio e può danneggiare potenzialmente i dati e rappresentare una minaccia alla sicurezza.

A partire da .NET Framework 2.0, la classe SafeHandle semplifica molti di questi problemi di durata degli oggetti e viene integrata con pInvoke in modo da evitare perdite delle risorse del sistema operativo. La classe SafeHandle risolve i problemi di durata degli oggetti assegnando e rilasciando handle senza interruzione. In essa è contenuto un finalizzatore critico che verifica che l'handle sia chiuso e ne garantisce l'esecuzione durante gli scaricamenti AppDomain, anche nei casi in cui si presuppone che la chiamata pInvoke sia in uno stato danneggiato.

Poiché la classe SafeHandle eredita dalla classe CriticalFinalizerObject, tutti i finalizzatori non critici vengono chiamati prima di eventuali finalizzatori critici. I finalizzatori vengono chiamati su oggetti non più attivi durante lo stesso passaggio della Garbage Collection. Un oggetto FileStream ad esempio può eseguire un finalizzatore normale per rimuovere i dati memorizzati nel buffer senza il rischio che l'handle vada perduto o venga riciclato. Questo ordinamento tra finalizzatori critici e non critici non è stato ideato per un utilizzo generale. Lo scopo principale è quello di fornire assistenza nella migrazione di librerie esistenti consentendo a tali librerie di utilizzare la classe SafeHandle senza modificare la semantica. Il finalizzatore critico e gli oggetti da esso chiamati, ad esempio il metodo SafeHandle.ReleaseHandle(), devono inoltre essere contenuti in un'area di esecuzione vincolata. In questo modo vengono imposti vincoli sul codice che è possibile scrivere nell'ambito del grafico chiamate del finalizzatore.

A partire da .NET Framework versione 2.0, le operazioni pInvoke incrementano automaticamente il numero dei riferimenti degli handle incapsulati da una classe SafeHandle e riducono tale numero dopo il completamento. In questo modo si evita che l'handle venga riciclato o chiuso in modo imprevisto.

È possibile specificare la proprietà dell'handle sottostante durante la costruzione di oggetti SafeHandle. In questo modo è possibile definire se l'oggetto SafeHandle rilascerà l'handle dopo l'eliminazione. Questa soluzione si rivela utile per gli handle con requisiti di durata particolari o per l'utilizzo di un handle la cui durata è controllata da altri fattori.

La classe SafeHandle nello spazio dei nomi System.Runtime.InteropServices è una classe wrapper astratta per gli handle del sistema operativo. La derivazione da questa classe è difficile. Utilizzare invece le classi derivate nello spazio dei nomi Microsoft.Win32.SafeHandles che forniscono handle sicuri per gli elementi seguenti:

  • File e pipe.

  • Visualizzazioni di memoria.

  • Costrutti di crittografia.

  • Chiavi del Registro di sistema.

  • Handle di attesa.

Mostra: