Partilhar via


Arquitetura de depuração CLR

O common linguagem tempo de execução (CLR) API de depuração foi projetado para ser usado sistema autônomo se fosse parte do kernel do sistema operacional. Em código não gerenciado, quando um programa gera uma exceção, o kernel suspende a execução do processo e passa as informações de exceção para o depurador usando o Win32 API de depuração. API de depuração CLR fornece a mesma funcionalidade para código gerenciado. Quando o código gerenciado gera uma exceção, API de depuração CLR suspende a execução do processo e passa as informações de exceção para o depurador.

Este tópico descreve como e quando o CLR depuração API obtém envolvidos e que ele de serviços fornece.

Arquitetura de processo

API de depuração CLR inclui os seguintes componentes principais dois:

  • A DLL de depuração, que é sempre carregado no mesmo processo sistema autônomo o programa que está sendo depurado. O controlador de tempo de execução é responsável pela comunicação com o CLR e execução de controle de execução e inspeção de segmentos que estão executando o código gerenciado.

  • A interface do depurador, que é carregada em um processo diferente do programa que está sendo depurado. A interface do depurador é responsável pela comunicação com o controlador de tempo de execução em nome do depurador. Também é responsável pela manipulação de eventos de depuração de Win32 de processo que está sendo depurado e qualquer tratamento desses eventos ou passá-los para um depurador de código não gerenciado. A interface de depurador é a única parte da API que tem uma API exposta de depuração CLR.

A ilustração a seguir mostra onde os diferentes componentes do CLR API de depuração estão localizados e como eles interagem com o CLR e o depurador.

Arquitetura de API de depuração CLR

Arquitetura de depuração CLR

Depurador de código gerenciado

É possível criar um depurador que oferece suporte somente para código gerenciado. API de depuração CLR permite que tal um depurador para anexar a um processo sob demanda, usando um Anexar suave mecanismo. Um depurador soft-anexado a um processo, em seguida, poderá desanexar do processo.

Sincronização de Segmento

API de depuração CLR tem requisitos conflitantes relativas à arquitetura de processos. Em uma mão, há vários motivos convincentes para manter a lógica de depuração no mesmo processo sistema autônomo o programa que está sendo depurado. Por exemplo, as estruturas de dados são complexas e com freqüência são manipuladas por funções em vez de um layout de memória fixa. É muito mais fácil telefonar as funções diretamente em vez de tentar decodificar as estruturas de dados de fora do processo. Outro motivo para manter a lógica de depuração no mesmo processo é para melhorar o desempenho, removendo a sobrecarga de comunicação entre processos. Por fim, um recurso importante de depuração CLR é a capacidade de executar o código do usuário no processo com o depurado, que obviamente requer algumas cooperação com o processo de depuração.

Por Outros lado, depuração CLR deve coexistir com depuração de código não gerenciado, que só pode ser executada corretamente de um processo externo. Além disso, um depurador fora de processo é mais seguro do que um depurador em processo, pois a interferência entre operação o depurador na e o processo de depuração é minimizada em um depurador fora de processo.

Devido um desses requisitos conflitantes, API de depuração CLR combina alguns dos cada abordagem. A principal interface de depuração é fora de processo e coexiste com os serviços de depuração nativo do Win32. No entanto, o CLR API de depuração adiciona a capacidade de sincronizar com o processo de depuração para que ele com segurança possa executar código no processo de usuário. Para executar a sincronização, a API colabora com o sistema operacional e o CLR para suspender todos os threads do processo em um local onde não interromper uma operação e deixar o tempo de execução em um estado incoerentes. O depurador, em seguida, é capaz de executar código em um thread especial que pode examinar o estado do tempo de execução e chamar o código do usuário se necessário.

Quando o código gerenciado executa uma instrução de ponto de interrupção ou gera uma exceção, o controlador de tempo de execução é notificado. Este componente determinará quais segmentos estão executando código gerenciado e quais segmentos estão executando o código não gerenciado. Em geral, segmentos que estão executando o código gerenciado serão permitidos para continuar a execução até que elas atinjam um estado onde eles podem ser com segurança suspenso. Por exemplo, eles podem precisar concluir uma coleta de lixo em andamento. Quando os segmentos de código gerenciado tiverem chegado estados de seguros, todos os threads são suspensos. A interface do depurador, em seguida, informa o depurador que um ponto de interrupção ou exceção foi recebida.

Quando código não gerenciado executa uma instrução de ponto de interrupção ou gera uma exceção, o componente de interface de depurador recebe notificação por meio do Win32 API de depuração. Esta notificação é passada para um depurador não gerenciado. Se o depurador decidir que deseja executar a sincronização (por exemplo, para que a pilha de código podem ser olhados quadros que gerenciado), a interface de depurador deve primeiro reiniciar o processo depurado interrompido e, em seguida, informe o controlador de tempo de execução para executar a sincronização. A interface do depurador, em seguida, é notificada quando a sincronização for concluída. Essa sincronização é transparente para o depurador não gerenciado.

O thread que gerou instrução de ponto de interrupção ou exceção não deve ter permissão para executar durante o processo de sincronização. Para facilitar isso, a interface de depurador assume o controle do thread, colocando um filtro de exceção especial na cadeia de filtro do segmento. Quando o segmento é reiniciado, ele inserirá o filtro de exceção, o thread sob controle do controlador de tempo de execução, será exibida. Quando for o time para continuar o processamento de exceção (ou time para cancelar a exceção), o filtro irá retornar controle para a cadeia de filtro exceção regular do thread ou retornar o resultado correto para continuar a execução.

Em casos raros, o thread que gera o nativo exceção pode ser mantendo bloqueios importantes que devem ser liberados antes de concluir a sincronização do tempo de execução. (Normalmente serão bloqueios de biblioteca de nível inferior, sistema autônomo bloqueios na malloc heap). Nesses casos, a operação de sincronização deve expirar e a sincronização falhará. Isso fará com que determinadas operações que requerem sincronização também falha.

O auxiliar de thread em processo

Um segmento auxiliar do único depurador é usado dentro de cada processo do CLR para certificar-se de que o CLR API de depuração funcione corretamente. Esse thread auxiliar é responsável pela manipulação muitos dos serviços de inspeção fornecidos pela API depuração, bem como ajudando com sincronização de threads em determinadas circunstâncias. Você pode usar o ICorDebugProcess::GetHelperThreadID método para identificar o thread auxiliar.

Interações com compiladores JIT

Para permitem a um depurador just-in-time (JIT) depurar código compilado, o CLR API de depuração deve ser capaz de mapear informações da versão Microsoft intermediate linguagem (MSIL) de uma função para a versão da função nativa. Essas informações incluem pontos de sequência no código e informações de variável local. Nas versões do .NET estrutura 1.0 e 1.1, essa informação foi produzida apenas quando o tempo de execução estava no modo de depuração. No .NET estrutura 2.0, essas informações são produzidas o time todo.

Além disso, o código com compilação JIT pode ser altamente otimizado. Otimizações, sistema autônomo eliminação subexpressão comuns, expansão embutido de funções, loop desenrolar, código hoisting e assim por diante podem levar à perda de correlação entre o código MSIL de uma função e o código nativo que será chamado para executá-lo. Assim, capacidade do compilador JIT de fornecer informações de mapeamento correto gravemente é afetada por essas técnicas de otimização de código agressivo. Portanto, quando o tempo de execução é executado no modo de depuração, o compilador JIT não executará algumas otimizações. Essa restrição permite que os depuradores determinar com precisão o mapeamento da fonte de linha e o local de todos os argumentos e variáveis locais.

Modos de depuração

API de depuração CLR fornece modos especiais para depuração nos dois casos:

  • Modo de edição e continuação. Nesse caso, o tempo de execução funciona de modo diferente para permitir que o código a ser alterada posteriormente. Isso ocorre porque o layout de determinadas estruturas de dados de time de execução deve ser diferente para oferecer suporte edição e continuar. Como isso tem um efeito adverso no desempenho, não use esse modo, a menos que você deseja edição e continuar a funcionalidade.

  • Modo de depuração. Esse modo permite que o compilador JIT omitir otimizações. Portanto, faz a execução de código nativo vincular mais de perto a linguagem de alto nível de fonte. Não use esse modo, a menos que seja necessário, pois ele também tem um efeito adverso no desempenho.

Se você depurar um programa fora Edit and Continue modo, a funcionalidade de edição e continuação não é suportada. Se você depurar um programa fora do modo de depuração, a maioria dos recursos de depuração ainda haverá suporte para, mas otimizações podem causar comportamento estranho. Por exemplo, revisão único pode parecer saltar aleatoriamente de uma linha para outra no método e métodos embutidos podem não aparecer em um rastreamento de pilha.

Um depurador pode habilitar edição e continuar e depuração modos através de programação por meio do CLR API de depuração se o depurador assumir o controle de um processo antes do tempo de execução foi inicializado propriamente dito. Isso é suficiente para várias finalidades. No entanto, um depurador que conecta a um processo que já foi executado por um tempo (por exemplo, durante a depuração JIT) não poderá iniciar os modos.

Para ajudar a lidar com esses problemas, um programa pode ser executado no modo de JIT ou no modo de depuração independentemente de um depurador. Para obter informações sobre maneiras de ativar a depuração, consulte Depuração e perfil de aplicativos.

Otimizações JIT podem tornar um aplicativo menos depurável. API de depuração CLR habilita a inspeção de quadros de pilha e variáveis locais com o código compilado JIT que foi otimizado. Revisão é suportado, mas pode ser impreciso. Você pode executar um programa que instrui o compilador JIT para desativar todas as otimizações JIT para produzir código depurável. Para obter detalhes, consulte:Fazer uma imagem mais fácil para Depurar.

Consulte também

Outros recursos

Depuração no .NET estrutura

Visão geral sobre depuração do CLR

Depuração (referência de API não gerenciada)