Partilhar via


Tornando uma imagem mais fácil de depurar no .NET

Nota

Este artigo é específico do .NET Framework. Ele não se aplica a implementações mais recentes do .NET, incluindo o .NET 6 e versões posteriores.

Ao compilar código não gerenciado, você pode configurar uma imagem executável para depuração definindo opções IDE ou opções de linha de comando. Por exemplo, você pode usar a opção de linha de comando /Zi no Visual C++ para pedir que ele emita arquivos de símbolo de depuração (extensão de arquivo .pdb). Da mesma forma, a opção de linha de comando /Od diz ao compilador para desativar a otimização. O código resultante é executado mais lentamente, mas é mais fácil de depurar, caso seja necessário.

Ao compilar código gerenciado do .NET Framework, compiladores como Visual C++, Visual Basic e C# compilam seu programa de origem em linguagem intermediária comum (CIL). O CIL é então compilado em JIT, imediatamente antes da execução, em código de máquina nativo. Assim como no código não gerenciado, você pode configurar uma imagem executável para depuração definindo opções IDE ou opções de linha de comando. Você também pode configurar a compilação JIT para depuração da mesma maneira.

Esta configuração JIT tem dois aspetos:

  • Você pode solicitar que o compilador JIT gere informações de rastreamento. Isso torna possível para o depurador corresponder uma cadeia de CIL com sua contraparte de código de máquina e rastrear onde as variáveis locais e os argumentos de função são armazenados. No .NET Framework versão 2.0 e posterior, o compilador JIT sempre gera informações de rastreamento, portanto, não há necessidade de solicitá-las.

  • Você pode solicitar ao compilador JIT que não otimize o código de máquina resultante.

Normalmente, o compilador que gera o CIL define essas opções do compilador JIT adequadamente, com base nas opções IDE ou opções de linha de comando especificadas, por exemplo, /Od.

Em alguns casos, talvez você queira alterar o comportamento do compilador JIT para que o código da máquina que ele gera seja mais fácil de depurar. Por exemplo, talvez você queira gerar informações de rastreamento JIT para uma compilação de varejo ou otimização de controle. Você pode fazer isso com um arquivo de inicialização (.ini).

Por exemplo, se o assembly que você deseja depurar é chamado MyApp.exe, então você pode criar um arquivo de texto chamado MyApp.ini, na mesma pasta que MyApp.exe, que contém estas três linhas:

[.NET Framework Debugging Control]
GenerateTrackingInfo=1
AllowOptimize=0

Você pode definir o valor de cada opção como 0 ou 1, e qualquer opção ausente assume como padrão 0. A configuração GenerateTrackingInfo como 1 e AllowOptimize 0 fornece a depuração mais fácil.

A partir do .NET Framework 2.0, o compilador JIT sempre gera informações de rastreamento, independentemente do valor para GenerateTrackingInfo, no entanto, o AllowOptimize valor ainda tem um efeito. Ao usar o Ngen.exe (Native Image Generator) para pré-compilar a imagem nativa sem otimização, o arquivo .ini deve estar presente na pasta de destino com AllowOptimize=0 quando Ngen.exe executa. Se você pré-compilou um assembly sem otimização, você deve remover o código pré-compilado usando NGen.exe opção /uninstall antes de executar novamente Ngen.exe pré-compilar o código como otimizado. Se o arquivo .ini não estiver presente na pasta, por padrão, Ngen.exe pré-compila o código conforme otimizado.

O System.Diagnostics.DebuggableAttribute controla as configurações de um assembly. DebuggableAttribute inclui dois campos que controlam se o compilador JIT deve otimizar e/ou gerar informações de rastreamento. No .NET Framework 2.0 e versões posteriores, o compilador JIT sempre gera informações de rastreamento.

Para uma compilação de varejo, os compiladores não definem nenhum DebuggableAttribute. Por padrão, o compilador JIT gera o mais alto desempenho, o código da máquina mais difícil de depurar. Habilitar o rastreamento JIT reduz um pouco o desempenho, e desativar a otimização diminui muito o desempenho.

O DebuggableAttribute aplica-se a um assembly inteiro de cada vez, não a módulos individuais dentro do assembly. As ferramentas de desenvolvimento devem, portanto, anexar atributos personalizados ao token de metadados do assembly, se um assembly já tiver sido criado, ou à classe chamada System.Runtime.CompilerServices.AssemblyAttributesGoHere. Em seguida, a ferramenta ALink promove esses atributos DebuggableAttribute de cada módulo para o assembly do qual eles se tornam parte. Se houver um conflito, a operação ALink falhará.

Nota

Na versão 1.0 do .NET Framework, o compilador do Microsoft Visual C++ adiciona o DebuggableAttribute quando as opções do compilador /clr e /Zi são especificadas. Na versão 1.1 do .NET Framework, você deve adicionar o DebuggableAttribute manualmente em seu código ou usar a opção de vinculador /ASSEMBLYDEBUG .

Consulte também