Partilhar via


Depuração dinâmica C++ (Pré-visualização)

Importante

A Depuração Dinâmica C++ está atualmente em pré-visualização. Essas informações estão relacionadas a um recurso de pré-lançamento que pode ser substancialmente modificado antes do lançamento. A Microsoft não oferece garantias, expressas ou implícitas, em relação às informações fornecidas aqui.

Este recurso de visualização, disponível a partir do Visual Studio 2022 Versão 17.14 Preview 2, aplica-se apenas a projetos x64.

Com a depuração dinâmica C++, você pode depurar o código otimizado como se ele não estivesse otimizado. Esse recurso é útil para desenvolvedores que exigem os benefícios de desempenho do código otimizado, como desenvolvedores de jogos que precisam de altas taxas de quadros. Com a depuração dinâmica C++, você pode aproveitar a experiência de depuração de código não otimizado sem sacrificar as vantagens de desempenho de compilações otimizadas.

A depuração de código otimizado apresenta desafios. O compilador reposiciona e reorganiza instruções para otimizar o código. O resultado é um código mais eficiente, mas significa:

  • O otimizador pode remover variáveis locais ou movê-las para locais desconhecidos para o depurador.
  • O código dentro de uma função pode não estar mais alinhado com o código-fonte quando o otimizador mescla blocos de código.
  • Os nomes de função para funções na pilha de chamadas podem estar errados se o otimizador mesclar duas funções.

No passado, os desenvolvedores lidavam com esses problemas e outros quando estavam no processo de depuração de código otimizado. Agora, esses desafios são eliminados porque com a depuração dinâmica C++ você pode entrar em código otimizado como se ele não estivesse otimizado.

Além de gerar os binários otimizados, compilar com /dynamicdeopt gera binários não otimizados que são usados durante a depuração. Quando você adiciona um ponto de interrupção ou entra em uma função (incluindo __forceinline funções), o depurador carrega o binário não otimizado. Em seguida, você pode depurar o código não otimizado para a função em vez do código otimizado. Você pode depurar como se estivesse depurando código não otimizado enquanto ainda obtém as vantagens de desempenho do código otimizado no resto do programa.

Experimente a depuração dinâmica C++

Primeiro, vamos analisar como é depurar código otimizado. Então você pode ver como a depuração dinâmica C++ simplifica o processo.

  1. Crie um novo projeto de aplicativo de console C++ no Visual Studio. Substitua o conteúdo do arquivo ConsoleApplication.cpp com o seguinte código:

    // Code generated by GitHub Copilot
    #include <iostream>
    #include <chrono>
    #include <thread>
    
    using namespace std;
    
    int step = 0;
    const int rows = 20;
    const int cols = 40;
    
    void printGrid(int grid[rows][cols])
    {
        cout << "Step: " << step << endl;
        for (int i = 0; i < rows; ++i)
        {
            for (int j = 0; j < cols; ++j)
            {
                cout << (grid[i][j] ? '*' : ' ');
            }
            cout << endl;
        }
    }
    
    int countNeighbors(int grid[rows][cols], int x, int y)
    {
        int count = 0;
        for (int i = -1; i <= 1; ++i)
        {
            for (int j = -1; j <= 1; ++j)
            {
                if (i == 0 && j == 0)
                {
                    continue;
                }
    
                int ni = x + i;
                int nj = y + j;
                if (ni >= 0 && ni < rows && nj >= 0 && nj < cols)
                {
                    count += grid[ni][nj];
                }
            }
        }
        return count;
    }
    
    void updateGrid(int grid[rows][cols])
    {
        int newGrid[rows][cols] = { 0 };
        for (int i = 0; i < rows; ++i)
        {
            for (int j = 0; j < cols; ++j)
            {
                int neighbors = countNeighbors(grid, i, j);
                if (grid[i][j] == 1)
                {
                    newGrid[i][j] = (neighbors < 2 || neighbors > 3) ? 0 : 1;
                }
                else
                {
                    newGrid[i][j] = (neighbors == 3) ? 1 : 0;
                }
            }
        }
        // Copy newGrid back to grid
        for (int i = 0; i < rows; ++i)
        {
            for (int j = 0; j < cols; ++j)
            {
                grid[i][j] = newGrid[i][j];
            }
        }
    }
    
    int main()
    {
        int grid[rows][cols] = { 0 };
    
        // Initial configuration (a simple glider)
        grid[1][2] = 1;
        grid[2][3] = 1;
        grid[3][1] = 1;
        grid[3][2] = 1;
        grid[3][3] = 1;
    
        while (true)
        {
            printGrid(grid);
            updateGrid(grid);
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
            cout << "\033[H\033[J"; // Clear the screen
            step++;
        }
    
        return 0;
    }
    
  2. Altere a lista suspensa Configurações da solução para Versão. Certifique-se de que a lista suspensa da plataforma de soluções esteja configurada para x64.

  3. Reconstrua selecionando Build>Rebuild Solution.

  4. Defina um ponto de interrupção na linha 55, int neighbors = countNeighbors(grid, i, j); em updateGrid(). Execute o programa.

  5. Quando atingires o ponto de interrupção, consulta a janela Locais. No menu principal, selecione Depurar>Windows>Locais. Observe que você não pode ver o valor de i ou j na janela Locais . O compilador eliminou-os através de otimização.

  6. Tente definir um ponto de interrupção na linha 19, cout << (grid[i][j] ? '*' : ' '); em printGrid(). Não pode fazê-lo. Esse comportamento é esperado porque o compilador otimizou o código.

Pare o programa e ative a depuração dinâmica C++ e tente novamente

  1. No Gerenciador de Soluções, clique com o botão direito do mouse no projeto e selecione Propriedades para abrir as páginas de propriedades do projeto.

  2. Selecione Advanced>Use C++ Dynamic Debugging, e altere a configuração para Sim.

    Uma captura de tela que mostra as propriedades avançadas do projeto.

    A página de propriedades abre-se em Propriedades de configuração > Avançado > Usar depuração dinâmica C++. A propriedade está configurada para "Sim".

    Esta etapa adiciona o /dynamicdeopt switch ao compilador e ao vinculador. Nos bastidores, ele também desliga as opções de otimização /GL e /OPT:ICF do C++. Essa configuração não substitui as opções adicionadas manualmente à linha de comando ou outras opções de otimização definidas, como /O1.

  3. Reconstrua selecionando Build>Rebuild Solution. O código MSB8088 de diagnóstico de compilação é exibido, o que indica que a depuração dinâmica e a otimização de todo o programa são incompatíveis. Este erro significa que toda a otimização do programa (/GL) foi automaticamente desativada durante a compilação.

    Você pode desativar manualmente toda a otimização do programa nas propriedades do projeto. Selecione Propriedades>de configuração Otimização avançada>de todo o programa e altere a configuração para Desativado. Agora MSB8088 é tratado como um aviso, mas pode ser tratado como um erro em uma versão futura do Visual Studio.

  4. Execute novamente o aplicativo.

    Agora, quando você atinge o ponto de interrupção na linha 55, você vê os valores de i e j na janela Locais . A janela Pilha de chamadas mostra que updateGrid() está desotimizada e o nome do arquivo é life.alt.exe. Este binário alternativo é usado para depurar código otimizado.

    Uma captura de ecrã que mostra a depuração da função updateGrid.

    Um ponto de interrupção é mostrado na função updateGrid. A pilha de chamadas mostra que a função está desotimizada e o nome do arquivo é life.alt.exe. A janela Locais mostra os valores de i e j e as outras variáveis locais na função.

    A updateGrid() função é desotimizada sob demanda porque você define um ponto de interrupção nela. Se você passar por cima de uma função otimizada durante a depuração, ela não será desotimizada. Se você entrar em uma função, ela será desotimizada. A principal maneira de fazer com que uma função seja desotimizada é se você definir um ponto de interrupção nela ou entrar nela.

    Você também pode desotimizar uma função na janela Pilha de chamadas . Clique com o botão direito do mouse na função ou em um grupo selecionado de funções e selecione Desotimizar na próxima entrada. Esse recurso é útil quando você deseja exibir variáveis locais em uma função otimizada para a qual você não definiu um ponto de interrupção em outro lugar na pilha de chamadas. As funções que são desotimizadas dessa maneira são agrupadas na janela Pontos de interrupção como um grupo de pontos de interrupção chamado Funções desotimizadas. Se você excluir o grupo de pontos de interrupção, as funções associadas serão revertidas para seu estado otimizado.

Usar pontos de interrupção condicionais e dependentes

  1. Tente definir um ponto de interrupção novamente na linha 19, cout << (grid[i][j] ? '*' : ' '); em printGrid(). Agora funciona. Colocar um ponto de interrupção na função desotimiza-a, permitindo assim depurá-la normalmente.

  2. Clique com o botão direito do mouse no ponto de interrupção na linha 19, selecione Condições e defina a condição como i == 10 && j== 10. Em seguida, selecione a caixa de seleção Ativar somente quando o seguinte ponto de interrupção for atingido: . Selecione o ponto de interrupção na linha 55 na lista suspensa. Agora, o ponto de interrupção na linha 19 só é acionado depois que o ponto de interrupção na linha 50 for ativado primeiro, e em seguida, quando grid[10][10] estiver prestes a ser exibido no console.

    O ponto é que você pode definir pontos de interrupção condicionais e dependentes em uma função otimizada e usar variáveis locais e linhas de código que, em uma compilação otimizada, podem não estar disponíveis para o depurador.

    Uma captura de tela que mostra as configurações de ponto de interrupção condicional para a linha 19.

    Um ponto de interrupção condicional é mostrado na linha 19, cout < < (grid[i][j] ? '*' : ' ');. A condição é definida como i == 10 && j== 10. A caixa de seleção Ativar somente quando o ponto de interrupção a seguir for atingido está marcada. A lista suspensa de ponto de interrupção é definida como life.cpp linha 55.

  3. Continue executando o aplicativo. Quando o ponto de interrupção na linha 19 for atingido, você poderá clicar com o botão direito do mouse na linha 15 e selecionar Definir próxima instrução para executar novamente o loop.

    Uma captura de tela que mostra a depuração da função printGrid.

    Um ponto de interrupção condicional e dependente é atingido na linha 19, cout < < (grid[i][j] ? '*' : ' ');. A janela Locais mostra os valores de i e j e as outras variáveis locais na função. A janela Call Stack mostra que a função está desotimizada e o nome do arquivo é life.alt.exe.

  4. Exclua todos os pontos de interrupção para retornar as funções desotimizadas ao seu estado otimizado. No menu principal do Visual Studio, selecione Depurar>Excluir Todos os Pontos de Interrupção. Em seguida, todas as funções retornam ao seu estado otimizado.

    Se adicionar pontos de interrupção através da opção Desotimizar na próxima entrada da janela Pilha de chamadas, algo que não fizemos neste passo a passo, pode clicar com o botão direito no grupo Funções desotimizadas e selecionar Excluir para reverter apenas as funções desse grupo para o seu estado otimizado.

    Uma captura de ecrã da janela de Breakpoints.

    A janela Pontos de interrupção mostra o grupo Funções desotimizadas. O grupo é selecionado e o menu de contexto é aberto com Eliminar grupo de pontos de paragem selecionado.

Desativar a depuração dinâmica do C++

Talvez seja necessário depurar o código otimizado sem que ele seja desotimizado ou colocar um ponto de interrupção no código otimizado e fazer com que o código permaneça otimizado quando o ponto de interrupção for atingido. Há várias maneiras de desativar a Depuração Dinâmica ou impedir que ela desotimize o código quando você atingir um ponto de interrupção:

  • No menu principal do Visual Studio, selecioneOpções de ferramentas>. No painel Opções, expanda a secção Todas as Definições>Depuração>Geral. Desmarque a opção Desotimizar automaticamente as funções depuradas quando possível (.NET 8+, depuração dinâmica C++). Da próxima vez que o depurador for iniciado, o código permanecerá otimizado.
  • No menu principal do Visual Studio, selecioneOpções de ferramentas>. Na caixa de diálogo Opções, expanda a seção Depuração>Geral. Desmarque a opção Desotimizar automaticamente as funções depuradas quando possível (.NET 8+, depuração dinâmica C++). Da próxima vez que o depurador for iniciado, o código permanecerá otimizado.
  • Vários dos pontos de paragem da depuração dinâmica são dois: um no binário otimizado e outro no binário não otimizado. Na janela Pontos de interrupção, selecione Mostrar Colunas>Função. Limpe o ponto de interrupção associado ao alt binário. O outro ponto de interrupção no par quebra no código otimizado.
  • Quando estiver a depurar, no menu principal do Visual Studio, selecione Depurar>Windows>Desmontagem. Certifique-se de que tem foco. Quando você entra em uma função através da janela Desmontagem , a função não será desotimizada.
  • Desative totalmente a depuração dinâmica não passando /dynamicdeopt para cl.exe, lib.exee link.exe. Caso estejas a utilizar bibliotecas de terceiros e não possas reconstruí-las, não passes /dynamicdeopt no final do link.exe para desativar a Depuração Dinâmica desse binário.
  • Para desativar rapidamente a Depuração Dinâmica para um único binário (por exemplo, test.dll), renomeie ou exclua o alt binário (por exemplo, test.alt.dll).
  • Para desativar a Depuração Dinâmica para um ou mais .cpp ficheiros, não inclua /dynamicdeopt ao criá-los. O restante do seu projeto é construído com depuração dinâmica.

Ativar depuração dinâmica C++ para Unreal Engine 5.6 ou posterior

O Unreal Engine 5.6 suporta depuração dinâmica C++ para Unreal Build Tool e Unreal Build Accelerator. Há duas maneiras de habilitá-lo. Modificar o BuildConfiguration.xml arquivo ou Modificar o Targets.cs arquivo.

Modificar o BuildConfiguration.xml ficheiro

No Visual Studio, selecione a configuração do Editor de Desenvolvimento e modifique BuildConfiguration.xml para incluir <bDynamicDebugging>true</bDynamicDebugging>. Para obter mais informações sobre BuildConfiguration.xml e seu local, consulte Configuração de compilação.

  1. Uma maneira de localizar seu BuildConfiguration.xml arquivo é executar uma compilação e verificar a saída do log de compilação. Por exemplo, ao criar o Lyra Starter Game, você vê uma saída como esta:

    - Running UnrealBuildTool: dotnet "..\..\Engine\Binaries\DotNET\UnrealBuildTool\UnrealBuildTool.dll" LyraEditor Win64 Development -Project="C:\LyraStarterGame\LyraStarterGame.uproject" ...
     14% -   Log file: C:\Users\<user>\AppData\Local\UnrealBuildTool\Log.txt
    
  2. Pesquise Log.txt por BuildConfiguration.xml. Deve conter uma linha como Reading configuration file from: C:\LyraStarterGame\Saved\UnrealBuildTool\BuildConfiguration.xml

  3. Modifique esse BuildConfiguration.xml arquivo para conter <bDynamicDebugging>true</bDynamicDebugging>:

    <?xml version="1.0" encoding="utf-8" ?>
    <Configuration xmlns="https://www.unrealengine.com/BuildConfiguration">
        <WindowsPlatform>
            <bDynamicDebugging>true</bDynamicDebugging> <!-- add this line -->
        </WindowsPlatform>
    </Configuration>
    

Modificar o Targets.cs ficheiro

A outra maneira de habilitar a depuração dinâmica C++ para Unreal Build Tool e Unreal Build Accelerator é modificar seu Target.cs arquivo para conter WindowsPlatform.bDynamicDebugging = true.

Os projetos do Unreal Engine têm Target.cs arquivos associados a vários tipos de destino, incluindo:

{ProjectName}.Target.cs for the game executable.
{ProjectName}Editor.Target.cs for the editor build.

Para uma compilação do {ProjectName}Editor.Target.cs editor, no arquivo, adicione WindowsPlatform.bDynamicDebugging = true; ao construtor:

public class LyraEditorTarget : TargetRules
{
    public LyraEditorTarget(TargetInfo Target) : base(Target)
    {
        Type = TargetType.Editor;

        WindowsPlatform.bDynamicDebugging = true; // add this line
        // Other settings...
    }
}

Ou para uma compilação de {ProjectName}.Target.cs jogo, no arquivo, adicione WindowsPlatform.bDynamicDebugging = true; a ApplyShared{Project name}TargetSettings():

internal static void ApplySharedLyraTargetSettings(TargetRules Target)
{
    ILogger Logger = Target.Logger;
    
    WindowsPlatform.bDynamicDebugging = true; // add this line
    // Other settings...
}

Para obter mais informações sobre os arquivos de destino do Unreal Engine, consulte Destinos.

Ativar depuração dinâmica C++ para Unreal Engine 5.5 ou anterior

Para o Unreal Engine 5.5 ou anterior, seleccione as alterações do Unreal Build Tool no GitHub para o seu repositório.

Observação

Para acessar os repositórios Epic no GitHub, você precisa de uma conta Epic e uma conta registrada no GitHub.

Depois de selecionar as alterações a serem aplicadas ao repositório, habilite bDynamicDebugging conforme descrito anteriormente. Você também precisa usar o Unreal Build Accelerator da Unreal Engine 5.6. Use os bits mais recentes do ue5-main ou desative o UBA adicionando o seguinte ao BuildConfiguration.xml:

<BuildConfiguration>
    <bAllowUBAExecutor>false</bAllowUBAExecutor>
    <bAllowUBALocalExecutor>false</bAllowUBALocalExecutor>
</BuildConfiguration>

Para mais informações sobre como o Unreal Engine é configurado, consulte Configuração de compilação.

Solução de problemas

Se os pontos de interrupção não forem atingidos em funções desotimizadas:

  • Se você sair de um [Deoptimized] quadro, poderá estar no código otimizado, a menos que o chamador tenha sido desotimizado devido a um ponto de interrupção nele ou você entre no chamador a caminho da função atual.

  • Certifique-se de que os arquivos alt.exe e alt.pdb foram construídos. Para test.exe e test.pdb, test.alt.exe e test.alt.pdb deve existir no mesmo diretório. Certifique-se de que as opções de compilação corretas estejam definidas de acordo com este artigo.

  • Existe uma debug directory entrada na test.exe qual o depurador usa para encontrar o alt binário a ser usado para Depuração Desotimizada. Abra um prompt de comando nativo do Visual Studio x64 e execute link /dump /headers <your executable.exe> para ver se existe uma deopt entrada. Uma deopt entrada aparece na Type coluna, como mostrado na última linha deste exemplo:

      Debug Directories
    
            Time Type        Size      RVA  Pointer
        -------- ------- -------- -------- --------
        67CF0DA2 cv            30 00076330    75330    Format: RSDS, {7290497A-E223-4DF6-9D61-2D7F2C9F54A0}, 58, D:\work\shadow\test.pdb
        67CF0DA2 feat          14 00076360    75360    Counts: Pre-VC++ 11.00=0, C/C++=205, /GS=205, /sdl=0, guardN=204
        67CF0DA2 coffgrp      36C 00076374    75374
        67CF0DA2 deopt         22 00076708    75708    Timestamp: 0x67cf0da2, size: 532480, name: test.alt.exe
    

    Se a deopt entrada do diretório de depuração não estiver lá, confirme se você está passando /dynamicdeopt para cl.exe, lib.exee link.exe.

  • A Desotimização Dinâmica não funcionará consistentemente se /dynamicdeopt não for passada para cl.exe, lib.exe e link.exe para todos os .cpp, .lib e arquivos binários. Confirme se as opções adequadas estão definidas quando você cria seu projeto.

Para obter mais informações sobre problemas conhecidos, consulte Depuração dinâmica C++: Depuração completa para compilações otimizadas.

Se as coisas não estiverem funcionando como esperado, abra um ticket na Comunidade de desenvolvedores. Inclua o máximo de informações possível sobre o problema.

Notas gerais

IncrediBuild 10.24 suporta compilações de depuração dinâmica C++.
O FastBuild v1.15 suporta compilações de depuração dinâmica C++.

As funções embutidas são desotimizadas sob demanda. Se você definir um ponto de interrupção em uma função embutida, o depurador desotimizará a função e seu chamador. O ponto de interrupção atinge onde você espera, como se seu programa tivesse sido construído sem otimizações do compilador.

Uma função permanece desotimizada mesmo se desativares os pontos de interrupção dentro dela. Você deve remover o ponto de interrupção para que a função reverta para seu estado otimizado.

Vários dos pontos de paragem da depuração dinâmica são dois: um no binário otimizado e outro no binário não otimizado. Por esse motivo, você vê mais de um ponto de interrupção na janela Pontos de interrupção .

Os sinalizadores do compilador que são usados para a versão desotimizada são os mesmos que são usados para a versão otimizada, exceto para sinalizadores de otimização e /dynamicdeopt. Esse comportamento significa que todos os sinalizadores definidos para definir macros, e assim por diante, também são definidos na versão desotimizada.

Código desotimizado não é o mesmo que código de depuração. O código desotimizado é compilado com os mesmos sinalizadores de otimização da versão otimizada, portanto, asserções e outros códigos que dependem de configurações específicas de depuração não são incluídos.

Construir integração de sistemas

A depuração dinâmica do C++ requer que os sinalizadores do compilador e do vinculador sejam definidos de uma maneira específica. As seções a seguir descrevem como configurar uma configuração dedicada para Depuração Dinâmica que não tenha opções conflitantes.

Se o seu projeto é criado com o sistema de compilação do Visual Studio, uma boa maneira de fazer uma configuração de Depuração Dinâmica é usar o Configuration Manager para clonar sua configuração Release ou Debug e fazer alterações para acomodar a Depuração Dinâmica. As duas seções a seguir descrevem os procedimentos.

Criar uma nova configuração de versão

  1. No menu principal do Visual Studio, selecione Build>Configuration Manager para abrir o Configuration Manager.

  2. Selecione a lista suspensa Configuração e depois selecione <Novo...>.

    Uma captura de ecrã que mostra o Gestor de configuração.

    No Configuration Manager, em Contextos de projeto, a lista suspensa Configuração está aberta e está realçada.

  3. A caixa de diálogo Nova configuração da solução é aberta. No campo Nome , insira um nome para a nova configuração, como ReleaseDD. Certifique-se de que Copiar configurações de: esteja definido como Liberar. Em seguida, selecione OK para criar a nova configuração.

    Uma captura de tela que mostra a caixa de diálogo Nova Configuração do Projeto para uma compilação de versão.

    O campo Nome está definido como ReleaseDD. A lista suspensa 'Copiar configurações de' está definida como Liberar.

  4. A nova configuração aparece na lista suspensa Configuração da solução ativa . Selecione Fechar.

  5. Com a lista suspensa Configuração definida como ReleaseDD, clique com o botão direito do mouse em seu projeto no Gerenciador de Soluções e selecione Propriedades.

  6. Em Propriedades>de configuração avançadas, defina Usar depuração dinâmica C++ como Sim.

  7. Certifique-se de que a Otimização de todo o programa está definida como Não.

    Uma captura de tela que mostra as propriedades avançadas do projeto.

    A página de propriedades é aberta para Propriedades de Configuração > Avançadas. Utilize a depuração dinâmica do C++. A propriedade está configurada para "Sim". A Otimização de Todo o Programa está definida como Não.

  8. Em Propriedades> de Linkador>Otimização, assegure-se de que Ativar dobramento COMDAT está definido como Não (/OPT:NOICF).

    Uma captura de tela que mostra as propriedades do projeto de otimização do Linker.

    A Página de Propriedades é aberta em Configuration Properties > Linker > Optimization > Enable CMDAT Folding. A propriedade está definida como Não (/OPT:NOICF).

Essa configuração adiciona o /dynamicdeopt switch ao compilador e ao vinculador. Com as opções /GL de otimização C++ e /OPT:ICF também desativadas, agora você pode criar e executar seu projeto na nova configuração quando quiser uma compilação de versão otimizada que possa ser usada com a depuração dinâmica C++.

Você pode adicionar outros interruptores que usa nas suas compilações comerciais a essa configuração, para que tenha sempre exatamente os interruptores ativados ou desativados conforme espera quando utiliza a Depuração Dinâmica. Para obter mais informações sobre opções que você não deve usar com a Depuração Dinâmica, consulte Opções incompatíveis.

Para obter mais informações sobre configurações no Visual Studio, consulte Criar e editar configurações.

Criar uma nova configuração de depuração

Se você quiser usar binários de depuração, mas quiser que eles sejam executados mais rapidamente, você pode modificar sua configuração de depuração.

  1. No menu principal do Visual Studio, selecione Build>Configuration Manager para abrir o Configuration Manager.

  2. Selecione a lista suspensa Configuração e depois selecione <Novo...>.

    Uma captura de ecrã que mostra o Gestor de configuração.

    No Configuration Manager, na secção de Contextos do projeto da janela, a lista suspensa Configuração está aberta e está destacado.

  3. A caixa de diálogo Nova configuração do projeto é aberta. No campo Nome , insira um nome para a nova configuração, como DebugDD. Assegure-se de que Copiar configurações de: está definido como Debug. Em seguida, selecione OK para criar a nova configuração.

    Uma captura de ecrã que mostra a

    O campo nome é definido como DebugDD. A lista suspensa Copiar configurações de: está definida como Depurar.

  4. A nova configuração aparece na lista suspensa Configuração da solução ativa . Selecione Fechar.

  5. Com a lista suspensa Configuração definida como DebugDD, clique com o botão direito do mouse em seu projeto no Gerenciador de Soluções e selecione Propriedades.

  6. Em Configuration Properties>C/C++>Optimization, ative as otimizações desejadas. Por exemplo, você pode definir Otimização para maximizar a velocidade (/O2).

  7. Em C/C++>Code Generation, defina Basic Runtime Checks como Default.

  8. Em C/C++>General, desative Support Just My Code Debugging.

  9. Defina Debug Information Format como Program Database (/zi).

Você pode adicionar outras opções que você usa com suas compilações de depuração a essa configuração para que você sempre tenha exatamente as opções ativadas ou desativadas que você espera quando usa a Depuração Dinâmica. Para obter mais informações sobre opções que você não deve usar com a Depuração Dinâmica, consulte Opções incompatíveis.

Para obter mais informações sobre configurações no Visual Studio, consulte Criar e editar configurações.

Considerações sobre o sistema de compilação personalizado

Se você tiver um sistema de compilação personalizado, certifique-se de que:

  • Passe /dynamicdeopt para cl.exe, lib.exee link.exe.
  • Não use /ZI, nenhuma das /RTC bandeiras, ou /JMC.

Para distribuidores de construção:

  • Para um projeto chamado test, o compilador produz test.alt.obj, test.alt.exp, test.obj, e test.exp. O vinculador produz test.alt.exe, test.alt.pdb, test.exe, e test.pdb.
  • Você precisa implantar o novo binário do conjunto de ferramentas c2dd.dll ao lado de c2.dll.

Opções incompatíveis

Algumas opções de compilador e vinculador são incompatíveis com a depuração dinâmica do C++. Se você ativar a depuração dinâmica C++ usando as configurações de projeto do Visual Studio, as opções incompatíveis serão desativadas automaticamente, a menos que você as defina especificamente na configuração de opções de linha de comando adicionais.

As seguintes opções do compilador são incompatíveis com a depuração dinâmica C++:

/GH
/GL
/Gh
/RTC1 
/RTCc 
/RTCs 
/RTCu 
/ZI (/Zi is OK)
/ZW 
/clr 
/clr:initialAppDomain
/clr:netcore
/clr:newSyntax
/clr:noAssembly
/clr:pure
/clr:safe
/fastcap
/fsanitize=address
/fsanitize=kernel-address

As seguintes opções de vinculador são incompatíveis com a depuração dinâmica C++:

/DEBUG:FASTLINK
/INCREMENTAL
/OPT:ICF  You can specify /OPT:ICF but the debugging experience may be poor

Ver também

/dynamicdeopt sinalizador do compilador (em pré-visualização)
/DYNAMICDEOPT sinalizador do ligador (pré-visualização)
Depuração Dinâmica C++: Depuração Completa para Compilações Otimizadas
Depurar código otimizado