Freigeben über


Sichere Handles und entscheidendes Abschließen

In Versionen vor .NET Framework, Version 2.0, konnten alle Betriebssystemhandles nur in das verwaltete IntPtr-Wrapper-Objekt gekapselt werden. Dies war zwar für die Zusammenarbeit mit systemeigenem Code praktisch, jedoch konnte es zu Handleverlusten durch asynchrone Ausnahmen kommen, z. B. durch einen unerwarteten Threadabbruch oder einen Stapelüberlauf. Diese asynchronen Ausnahmen behindern das Bereinigen von Betriebssystemressourcen und können an fast jeder Stelle des Programms auftreten. Sie sind besonders häufig in Anwendungen, in denen ein Host verwendet wird, der verwalteten Code ausführt (z. B. Microsoft SQL Server).

In manchen Fällen können finalisierbare Objekte durch eine Garbage Collection beim Ausführen einer Methode innerhalb eines Plattformaufrufs zurückgefordert werden. Wenn ein Finalizer das an den Plattformaufruf übergebene Handle freigibt, kann dies zu Handlebeschädigungen führen. Das Handle könnte auch zurückgefordert werden, wenn Ihre Methode während eines Plattformaufrufs blockiert ist, zum Beispiel beim Lesen einer Datei.

Aufgrund des verstärkten Handlerecyclings in Windows kann ein kritisches Problem auftreten, wenn ein Handle wiederverwendet wird und auf eine andere Ressource zeigt, die möglicherweise vertrauliche Informationen enthält. Bei einem solchen Recyclingangriff können Daten beschädigt werden, und es kann ein Sicherheitsrisiko auftreten.

Ab .NET Framework 2.0 werden mehrere dieser Probleme mit der Objektlebensdauer durch die SafeHandle-Klasse vereinfacht. Diese Klasse ist in den Plattformaufruf integriert, sodass Betriebssystemressourcenverluste nicht auftreten. Die SafeHandle-Klasse löst Probleme mit der Objektlebensdauer, indem sie Handles ohne Unterbrechung zuweist und freigibt. Sie enthält einen kritischen Finalizer, durch den sichergestellt wird, das das Handle geschlossen ist und während AppDomain-Entladungen garantiert ausgeführt wird. Dies geschieht selbst in Fällen, in denen angenommen wird, dass der Plattformaufruf beschädigt ist.

Da SafeHandle von CriticalFinalizerObject erbt, werden alle nicht-kritischen Finalizer immer vor den kritischen Finalizer aufgerufen. Die Finalizer werden für Objekte aufgerufen, die während des gleichen Garbage Collection-Durchgangs nicht mehr aktiv sind. Ein FileStream-Objekt kann beispielsweise einen normalen Finalizer ausführen, um vorhandene gepufferte Daten zu entfernen, ohne dabei zu riskieren, dass ein Handleverlust auftritt oder das Handle wiederverwendet wird. Diese sehr schwache Reihenfolge von kritischen und nicht-kritischen Finalizern ist nicht zur allgemeinen Verwendung bestimmt. Ihr Hauptzweck ist, bei der Migration von vorhandenen Bibliotheken zu helfen, indem sie diesen Bibliotheken erlaubt, das SafeHandle zu verwenden, ohne ihre Semantik zu verändern. Zudem müssen sich der kritische Finalizer und alle von diesem Finalizer aufgerufenen Elemente, wie z. B. die SafeHandle.ReleaseHandle()-Methode, in einem eingeschränkten Ausführungsbereich befinden Dadurch wird eingeschränkt, welcher Code innerhalb des Aufrufdiagramms des Finalizers geschrieben werden kann.

Ab .NET Framework, Version 2.0, wird der Referenzzähler von Handles, die von einem SafeHandle gekapselt werden, durch Plattformaufrufoperationen automatisch inkrementiert und nach Abschluss des Vorgangs dekrementiert. So wird sichergestellt, dass das Handle nicht wiederverwendet oder unerwartet geschlossen wird.

Sie können den Besitzer des zugrunde liegenden Handles angeben, wenn Sie SafeHandle-Objekte erstellen. So wird gesteuert, ob das SafeHandle-Objekt das Handle freigibt, nachdem das Objekt verworfen wird. Dies ist nützlich für Handles mit bestimmten Anforderungen an die Lebensdauer oder bei Verwendung eines Handles, dessen Lebensdauer von einer anderen Person gesteuert wird.

SafeHandle-Klassen

Die SafeHandle-Klasse im System.Runtime.InteropServices-Namespace ist eine abstrakte Wrapperklasse für Betriebssystemhandles. Das Ableiten von dieser Klasse ist schwierig. Verwenden Sie stattdessen die abgeleiteten Klassen im Microsoft.Win32.SafeHandles-Namespace, die sichere Handles für Folgendes bereitstellen:

  • Dateien und Pipes.

  • Speicheransichten.

  • Kryptografiekonstrukte.

  • Registrierungsschlüssel.

  • Wait-Handles.

Siehe auch

Referenz

SafeHandle

CriticalHandle

CriticalFinalizerObject