Partager via


Handles sécurisés et finalisation critique

Mise à jour : novembre 2007

Avant la version 2.0 du .NET Framework, tous les handles du système d'exploitation pouvaient être encapsulés uniquement dans l'objet de wrapper managé IntPtr. Même si c'était un moyen pratique d'interagir avec le code natif, les handles pouvaient être divulgués par des exceptions asynchrones, telles qu'un abandon inattendu de thread ou un dépassement de capacité de la pile. Ces exceptions asynchrones constituent un obstacle au nettoyage des ressources du système d'exploitation et peuvent se produire presque n'importe où dans votre programme. Elles sont susceptibles de se produire dans des applications qui utilisent un hôte exécutant du code managé, tel que Microsoft SQL Server.

Dans certaines circonstances, les objets finalisables pouvaient être récupérés par le garbage collection lors de l'exécution d'une méthode dans un appel de plateforme. Si un finaliseur libérait le handle passé à cet appel de plateforme, cela pouvait entraîner l'altération du handle. Le handle pouvait également être récupéré lorsque votre méthode était bloquée pendant un appel de plateforme, comme lors de la lecture d'un fichier.

Plus important : étant donné que Windows recycle les handles de manière agressive, un handle pouvait être recyclé et pointer vers une autre ressource pouvant contenir des données sensibles. C'est ce qu'on appelle une attaque de recyclage ; elle peut éventuellement endommager des données et être une menace pour la sécurité.

Depuis le .NET Framework 2.0, la classe SafeHandle simplifie plusieurs de ces problèmes de durée de vie des objets et est intégrée à l'appel de plateforme de sorte que ces ressources de système d'exploitation ne soient pas divulguées. La classe SafeHandle résout les problèmes de durée de vie des objets en assignant et en libérant des handles sans interruption. Elle contient un finaliseur critique qui garantit la fermeture du handle et son exécution pendant le déchargement de AppDomain, même dans les cas où l'appel de plateforme est censé être dans un état endommagé.

Étant donné que SafeHandle hérite de CriticalFinalizerObject, tous les finaliseurs non critiques sont appelés avant les finaliseurs critiques. Les finaliseurs sont appelés sur des objets qui ne sont plus vivants pendant le même passage de garbage collection. Par exemple, un objet FileStream peut exécuter un finaliseur normal pour nettoyer les données mises en mémoire tampon existantes sans risquer que le handle soit divulgué ou recyclé. Ce classement très subtil entre les finaliseurs critiques et non critiques n'est pas destiné à être utilisé de manière générale. Il existe essentiellement pour faciliter la migration de bibliothèques existantes en leur permettant d'utiliser SafeHandle sans modifier leur sémantique. En outre, le finaliseur critique et tout ce qu'il peut appeler, par exemple la méthode SafeHandle.ReleaseHandle(), doivent être dans une région d'exécution limitée. Cela impose des contraintes sur le code qui peut être écrit dans le graphique des appels du finaliseur.

Depuis le .NET Framework version 2.0, les opérations d'appel de plateforme incrémentent automatiquement le décompte de références de handles encapsulés par un SafeHandle et les décrémentent lors de l'achèvement. Cela garantit que le handle ne sera pas recyclé ou fermé de manière inattendue.

Vous pouvez spécifier la propriété du handle sous-jacent lors de la construction d'objets SafeHandle. Cela contrôle si l'objet SafeHandle libérera le handle après la suppression de l'objet. C'est utile pour les handles avec des impératifs de durée de vie particuliers ou pour consommer un handle dont la durée de vie est contrôlée par une autre personne.

Classes de handles sécurisés

L'espace de noms Microsoft.Win32.SafeHandles contient des classes dérivées de SafeHandle pour fournir des fonctionnalités de prise en charge des handles de fichiers et de systèmes d'exploitation. Le tableau suivant récapitule les classes de handles sécurisés du .NET Framework.

Classe

Description

SafeHandle

Encapsule un handle pour les opérations d'appel de plateforme garantissant une finalisation sans interruption. Cette classe doit être héritée.

SafeFileHandle

Fournit l'accès aux handles de fichiers non managés.

SafeWaitHandle

Fournit l'accès aux handles d'attente non managés.

SafeHandleMinusOneIsInvalid

et

SafeHandleZeroOrMinusOneIsInvalid

Permet de créer une classe de handle sécurisé personnalisée.

Voir aussi

Référence

SafeHandle

CriticalHandle

CriticalFinalizerObject