Partilhar via


releaseHandleFailed MDA

O releaseHandleFailed gerenciado depuração assistant (MDA) é ativado é notificar os desenvolvedores quando o ReleaseHandle método de uma classe derivada de SafeHandle ou CriticalHandle retorna false.

Sintomas

Vazamentos de memória ou recursos. Se o ReleaseHandle método da classe derivando de SafeHandle ou CriticalHandle falhar, então o recurso encapsulado pela classe não ter sido liberado ou limpos ativo. \

Causa

Os usuários devem fornecer a implementação da ReleaseHandle método se eles criarem classes que derivam de SafeHandle ou CriticalHandle; Assim, as circunstâncias são específicas para o recurso individual. No entanto, os requisitos são:

  • SafeHandlee CriticalHandle tipos representam wrappers em torno de recursos do processo vital. Um vazamento de memória seria inutilizar o processo ao longo do tempo.

  • O ReleaseHandle método não deve falhar executar sua função. Depois que o processo adquire o recurso, ReleaseHandle é a única maneira de liberar o proprietário. Portanto, a falha implica vazamentos de recurso.

  • Qualquer falha que ocorrem durante a execução de ReleaseHandle, impedir o lançamento do recurso, é um bug na implementação do ReleaseHandle próprio método. É responsabilidade do programador para garantir que o contrato seja cumprido, mesmo que o código chama o código escrito por alguém para executar sua função.

Resolução

O código que usa o específico do SafeHandle (ou CriticalHandle) tipo que gerou a notificação de MDA deve ser revisado, procurando os locais onde o valor do identificador bruto é extraído da SafeHandle e copiadas em outro lugar. Esta é a causa comum de falhas em SafeHandle ou CriticalHandle implementações, porque o uso do valor bruto de alça, em seguida, é não controladas pelo runtime. Se a cópia de alça brutos subseqüentemente estiver fechada, pode causar uma posterior ReleaseHandle chamada falhe, pois a tentativa de fechamento no mesmo identificador, que é agora inválido.

Há várias maneiras em que a duplicação de identificador incorreto pode ocorrer:

  • Procure chamadas para o DangerousGetHandle método. Chamadas para este método devem ser excessivamente raras e qualquer um que você encontrar deve ser cercada de chamadas para o DangerousAddRef e DangerousRelease métodos. Esses métodos último especificam a região de código na qual o valor do identificador brutos pode ser usado com segurança. Fora dessa região, ou se a contagem de referência nunca é incrementada em primeiro lugar, o valor do identificador pode ser invalidado a qualquer momento por uma chamada para Dispose ou Close em outro segmento. Uma vez, todos os usos de DangerousGetHandle foram controladas para baixo, você deve seguir o caminho que a alça de raw leva para garantir que ele não é encaminhado para o componente de eventualmente chamará CloseHandle ou outro método nativo baixo nível que lançará a alça.

  • Certifique-se de que o código que é usado para inicializar o SafeHandle com um identificador válido de raw é proprietária do valor do identificador. Se você formar um SafeHandle em torno de uma alça de seu código não possui sem definir o ownsHandle parâmetro para false no construtor base, em seguida, ambos o SafeHandle e o proprietário do identificador real pode tentar fechar o identificador, levando a um erro no ReleaseHandle se a SafeHandle perde a corrida.

  • Quando um SafeHandle é empacotado entre domínios de aplicativo, confirme a SafeHandle derivação sendo usada foi marcada como serializável. Nos raros casos onde uma classe derivada de SafeHandle foi feita serializável, deve implementar a ISerializable interface ou use uma das outras técnicas para controlar a serialização e desserialização manualmente o processo. Isso é necessário porque a ação de serialização padrão é para criar um clone de bit a bit do valor incluso alça raw, resultando em dois SafeHandle instâncias pensando que possuem o mesmo identificador. Ambos tentará chamar ReleaseHandle na mesma alça em algum ponto. A segunda SafeHandle para fazer este irá falhar. O curso correto de ação ao serializar um SafeHandle é chamar o DuplicateHandle função ou uma função semelhante para o seu tipo de identificador nativo fazer uma cópia de distinta identificador legal. Se o seu tipo de identificador não oferece suporte a isso, em seguida, o SafeHandle encapsulá-la de tipo não pode ser feito serializável.

  • É possível controlar onde um identificador está sendo fechado no início, levando a uma falha quando o ReleaseHandle método é chamado, finalmente, colocando um ponto de interrupção do depurador em que a rotina nativa usada para liberar o identificador, por exemplo o CloseHandle função. Isso talvez não seja possível para cenários de carga ou mesmo médias testes funcionais devido ao tráfego pesado com que dessas rotinas costumam lidam. Pode ser útil para instrumentar o código que chama o método release nativo, para capturar a identidade do chamador, ou, possivelmente, um rastreamento de pilha completo e o valor do identificador sendo lançado. O valor do identificador pode ser comparado com o valor informado por este MDA.

  • Observe que alguns tipos de identificador nativo, como, por exemplo, todos os Win32 manipula que pode ser liberado por meio de CloseHandle function, compartilhar o mesmo identificador de namespace. Uma versão incorreta do identificador de um tipo pode causar problemas com o outro. Por exemplo, o fechamento acidentalmente um identificador de evento do Win32 de duas vezes pode levar a um identificador de arquivo aparentemente não relacionados que está sendo fechado prematuramente. Isso acontece quando o identificador é liberado e o valor do identificador se torna disponível para ser usado controlar a outro recurso, potencialmente, de outro tipo. Se isso acontece e é seguido por uma segunda versão errada, a alça de um segmento não relacionado pode invalidada.

Efeito sobre o tempo de execução.

Este MDA não tem efeito sobre o CLR.

Saída

Uma mensagem indicando que uma SafeHandle ou CriticalHandle Falha ao liberar em corretamente a alça. Por exemplo:

"A SafeHandle or CriticalHandle of type 'MyBrokenSafeHandle' 
failed to properly release the handle with value 0x0000BEEF. This 
usually indicates that the handle was released incorrectly via 
another means (such as extracting the handle using DangerousGetHandle 
and closing it directly or building another SafeHandle around it."

Configuração

<mdaConfig>
  <assistants>
    <releaseHandleFailed/>
  </assistants>
</mdaConfig>

Exemplo

A seguir está um exemplo de código que pode ativar o releaseHandleFailed MDA.

bool ReleaseHandle()
{
    // Calling the Win32 CloseHandle function to release the 
    // native handle wrapped by this SafeHandle. This method returns 
    // false on failure, but should only fail if the input is invalid 
    // (which should not happen here). The method specifically must not 
    // fail simply because of lack of resources or other transient 
    // failures beyond the user’s control. That would make it unacceptable 
    // to call CloseHandle as part of the implementation of this method.
    return CloseHandle(handle);
}

Consulte também

Referência

MarshalAsAttribute

Conceitos

Diagnosticar erros com assistentes de depuração gerenciada

Interop Marshaling

Outros recursos

Interoperabilidade