Compartilhar via


Classe System.Runtime.InteropServices.SafeHandle

Este artigo fornece comentários complementares à documentação de referência para esta API.

A classe SafeHandle oferece finalização crítica dos recursos de identificador, impedindo que os identificadores sejam recolhidos prematuramente pela coleta de lixo e recicladas pelo sistema operacional para referenciar objetos não gerenciados indesejados.

Por que SafeHandle?

Embora as substituições do método Object.Finalize permitam a limpeza de recursos não gerenciados quando um objeto está sendo coletado, em algumas circunstâncias, objetos finalizáveis podem ser coletados novamente pela coleta de lixo enquanto executam um método em uma chamada de invocação de plataforma. Se um finalizador liberar o identificador passado para essa chamada de invocação de plataforma, isso poderá levar a lidar com a corrupção. Também é possível recuperar o identificador enquanto seu método é bloqueado durante uma chamada de invocação de plataforma, como ao ler um arquivo.

Mais importante, como o Windows recicla identificadores agressivamente, um identificador pode ser reciclado e apontar para outro recurso que possa conter dados confidenciais. Isso é conhecido como um ataque de reciclagem e pode potencialmente corromper dados e ser uma ameaça à segurança.

O que o SafeHandle faz

A SafeHandle classe simplifica vários desses problemas de tempo de vida do objeto e é integrada à invocação de plataforma para que os recursos do sistema operacional não sejam vazados. A SafeHandle classe resolve problemas de ciclo de vida do objeto ao atribuir e liberar identificadores sem interrupção. Ele contém um finalizador crítico que garante que o identificador esteja fechado e tenha a garantia de ser executado durante descarregamentos inesperados de AppDomain, mesmo nos casos em que a chamada de invocação da plataforma é considerada em um estado corrompido.

Como SafeHandle herda de CriticalFinalizerObject, todos os finalizadores não críticos são chamados antes de qualquer um dos finalizadores críticos. Os finalizadores são chamados em objetos que não estão mais ativos durante a mesma passagem de coleta de lixo. Por exemplo, um objeto FileStream pode executar um finalizador normal para eliminar dados em buffer existentes sem o risco de o identificador vazar ou ser reciclado. Essa ordenação muito fraca entre finalizadores críticos e não críticos não se destina ao uso geral. Ele existe principalmente para ajudar na migração de bibliotecas existentes, permitindo que essas bibliotecas usem SafeHandle sem alterar sua semântica. Além disso, o finalizador crítico e tudo o que ele chama, como o SafeHandle.ReleaseHandle() método, devem estar em uma região de execução restrita. Isso impõe restrições sobre qual código pode ser escrito no grafo de chamada do finalizador.

As operações de invocação de plataforma incrementam automaticamente a contagem de referência de identificadores encapsulados por um SafeHandle e a decrementam após a conclusão. Isso garante que o identificador não será reciclado ou fechado de forma inesperada.

Você pode especificar a propriedade do identificador subjacente ao construir objetos SafeHandle fornecendo um valor para o argumento ownsHandle no construtor da classe SafeHandle. Isso controla se o objeto SafeHandle liberará o identificador depois que o objeto tiver sido descartado. Isso é útil para identificadores com requisitos de tempo de vida peculiares ou para consumir um identificador cujo tempo de vida é controlado por outra pessoa.

Classes derivadas de SafeHandle

SafeHandle é uma classe de wrapper abstrata para identificadores do sistema operacional. Derivar a partir dessa classe é difícil. Em vez disso, use as classes derivadas no namespace Microsoft.Win32.SafeHandles que fornecem identificadores seguros para o seguinte: