Condividi tramite


Debug dinamico C++ (anteprima)

Importante

Il debugging dinamico di C++ è attualmente in anteprima. Queste informazioni si riferiscono a una funzionalità di versione non definitiva che potrebbe essere modificata sostanzialmente prima del rilascio. Microsoft non fornisce alcuna garanzia, espressa o implicita, in relazione alle informazioni fornite qui.

Questa funzionalità di anteprima, disponibile a partire da Visual Studio 2022 Versione 17.14 Preview 2, si applica solo ai progetti x64.

Con il debug dinamico C++ è possibile eseguire il debug di codice ottimizzato come se non fosse ottimizzato. Questa funzionalità è utile per gli sviluppatori che richiedono i vantaggi delle prestazioni del codice ottimizzato, ad esempio gli sviluppatori di giochi che necessitano di frequenze di fotogrammi elevate. Con il debug dinamico C++ è possibile usufruire dell'esperienza di debug di codice non ottimizzato senza sacrificare i vantaggi delle prestazioni delle compilazioni ottimizzate.

Il debug di codice ottimizzato presenta problemi. Il compilatore riposiziona e riorganizza le istruzioni per ottimizzare il codice. Il risultato è un codice più efficiente, ma significa:

  • Optimizer può rimuovere le variabili locali o spostarle in posizioni sconosciute al debugger.
  • Il codice all'interno di una funzione potrebbe non essere più allineato al codice sorgente quando Optimizer unisce blocchi di codice.
  • I nomi di funzione per le funzioni nello stack di chiamate potrebbero non essere corretti se l'utilità di ottimizzazione unisce due funzioni.

In passato, gli sviluppatori hanno affrontato questi problemi e altri quando erano nel processo di debug di codice ottimizzato. Ora queste sfide vengono eliminate perché con il debug dinamico C++ è possibile eseguire un'istruzione nel codice ottimizzato come se non fosse ottimizzata.

Oltre a generare i file binari ottimizzati, la compilazione con /dynamicdeopt genera file binari non ottimizzati usati durante il debug. Quando si aggiunge un punto di interruzione o si esegue il debug di una funzione (incluse le funzioni __forceinline), il debugger carica il file binario non ottimizzato. È quindi possibile eseguire il debug del codice non ottimizzato per la funzione invece del codice ottimizzato. È possibile eseguire il debug come se si esegue il debug di codice non ottimizzato mentre si ottengono comunque i vantaggi delle prestazioni del codice ottimizzato nel resto del programma.

Provare il debug dinamico C++

Prima di tutto, esaminiamo come eseguire il debug di codice ottimizzato. È quindi possibile vedere in che modo il debug dinamico C++ semplifica il processo.

  1. Creare un nuovo progetto di applicazione console C++ in Visual Studio. Sostituire il contenuto del file ConsoleApplication.cpp con il codice seguente:

    // 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. Cambiare il menu a tendina Configurazioni della soluzione in Release. Assicurarsi che l'elenco a discesa della piattaforma soluzioni sia impostato su x64.

  3. Ricompilare selezionando Compila>ricompila soluzione.

  4. Impostare un punto di interruzione nella riga 55, int neighbors = countNeighbors(grid, i, j); in updateGrid(). Eseguire il programma.

  5. Quando si raggiunge il punto di interruzione, visualizzate la finestra Variabili locali. Nel menu principale selezionare Debug>Windows>Locals. Si noti che non è possibile visualizzare il valore di i o j nella finestra Variabili locali . Il compilatore li ha ottimizzati eliminandoli.

  6. Provare a impostare un punto di interruzione nella riga 19, cout << (grid[i][j] ? '*' : ' '); in printGrid(). Non è possibile. Questo comportamento è previsto perché il compilatore ha ottimizzato il codice.

Arrestare il programma e abilitare il debug dinamico C++ e riprovare

  1. In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto e scegliere Proprietà per aprire le pagine delle proprietà del progetto.

  2. Selezionare Avanzate>Usa debug dinamico C++ e modificare l'impostazione su .

    Screenshot che mostra le proprietà avanzate del progetto.

    La pagina delle proprietà viene visualizzata in Proprietà di configurazione > Avanzate > Usa debug dinamico C++. La proprietà è impostata su Sì.

    Questo passaggio aggiunge l'opzione /dynamicdeopt al compilatore e al linker. Dietro le quinte, disattiva anche i commutatori /GL di ottimizzazione C++ e /OPT:ICF. Questa impostazione non sovrascrive le opzioni aggiunte manualmente alla riga di comando o ad altre opzioni di ottimizzazione impostate, ad esempio /O1.

  3. Ricompilare selezionando Compila>ricompila soluzione. Viene visualizzato il codice MSB8088 di diagnostica di compilazione, che indica che il debug dinamico e l'ottimizzazione dell'intero programma non sono compatibili. Questo errore indica che l'intera ottimizzazione del programma (/GL) è stata disattivata automaticamente durante la compilazione.

    È possibile disattivare manualmente l'ottimizzazione dell'intero programma nelle proprietà del progetto. Selezionare Proprietà >Ottimizzazioneavanzata>intero programma e modificare l'impostazione su Disattivato. Ora MSB8088 viene considerato come un avviso, ma potrebbe essere considerato come un errore in una versione futura di Visual Studio.

  4. Rieseguire l'app.

    Quando si raggiunge il punto di interruzione nella riga 55, vengono visualizzati i valori di i e j nella finestra Variabili locali . La finestra Stack di chiamate mostra che updateGrid() è deoptimizzato e il nome file è life.alt.exe. Questo file binario alternativo viene usato per eseguire il debug di codice ottimizzato.

    Screenshot che mostra il debug della funzione updateGrid.

    Un punto di interruzione viene visualizzato nella funzione updateGrid. Lo stack di chiamate mostra che la funzione è deoptimizzata e il nome file è life.alt.exe. La finestra Variabili locali mostra i valori di i e j e le altre variabili locali nella funzione.

    La updateGrid() funzione viene deoptimizzata su richiesta perché è stato impostato un punto di interruzione. Se si passa oltre una funzione ottimizzata durante il debug, non viene deottimizzata. Se si entra in una funzione, viene deottimizzata. Il modo principale per far sì che una funzione venga deottimizzata è impostare un punto di interruzione al suo interno o eseguire il passaggio all'interno di essa.

    È anche possibile deoptimizzare una funzione nella finestra Stack di chiamate . Fare clic con il pulsante destro del mouse sulla funzione o su un gruppo selezionato di funzioni e scegliere Deoptimize alla voce successiva. Questa funzionalità è utile quando si desidera visualizzare le variabili locali in una funzione ottimizzata per cui non è stato impostato un punto di interruzione altrove nello stack di chiamate. Le funzioni deoptimizzate in questo modo vengono raggruppate nella finestra Punti di interruzione come gruppo di punti di interruzione denominato Funzioni deoptimizzate. Se si elimina il gruppo di punti di interruzione, le funzioni associate ripristinano lo stato ottimizzato.

Usare punti di interruzione condizionali e dipendenti

  1. Provare a impostare di nuovo un punto di interruzione nella riga 19, cout << (grid[i][j] ? '*' : ' '); in printGrid(). Ora funziona. L'impostazione di un punto di interruzione nella funzione la deoptimizza in modo che sia possibile eseguirne il debug normalmente.

  2. Fare clic con il pulsante destro del mouse sul punto di interruzione nella riga 19, selezionare Condizioni e impostare la condizione su i == 10 && j== 10. Selezionare quindi la casella di controllo Abilita solo quando viene raggiunto il punto di interruzione seguente: . Selezionare il punto di interruzione nella riga 55 dall'elenco a discesa. Ora il punto di interruzione nella riga 19 non viene raggiunto finché il punto di interruzione nella riga 50 non viene attivato prima, e poi quando grid[10][10] sta per inviare l'output alla console.

    Il punto è che è possibile impostare punti di interruzione condizionali e dipendenti in una funzione ottimizzata e usare variabili locali e righe di codice che in una compilazione ottimizzata potrebbero non essere disponibili per il debugger.

    Screenshot che mostra le impostazioni del punto di interruzione condizionale per la riga 19.

    Un punto di interruzione condizionale viene visualizzato nella riga 19, cout < < (grid[i][j] ? '*' : ' ');. La condizione è impostata su i == 10 && j== 10. La casella di controllo per Abilita solo quando viene raggiunto il punto di interruzione seguente è selezionata. L'elenco a discesa del punto di interruzione è impostato su life.cpp riga 55.

  3. Continuare a eseguire l'app. Quando viene raggiunto il punto di interruzione nella riga 19, è possibile fare clic con il pulsante destro del mouse sulla riga 15 e scegliere Imposta istruzione successiva per rieseguire il ciclo.

    Screenshot che mostra il debug della funzione printGrid.

    Viene raggiunto un punto di interruzione condizionale e dipendente alla riga 19, cout < < (griglia[i][j] ? '*' : ' ');. La finestra Variabili locali mostra i valori di i e j e le altre variabili locali nella funzione. La finestra Stack di chiamate mostra che la funzione è deoptimizzata e il nome file è life.alt.exe.

  4. Eliminare tutti i punti di interruzione per restituire le funzioni deoptimizzate allo stato ottimizzato. Nel menu principale di Visual Studio selezionare Debug>Elimina tutti i punti di interruzione. Tutte le funzioni tornano quindi allo stato ottimizzato.

    Se si aggiungono punti di interruzione tramite l'opzione Deotimizza all'ingresso successivo nella finestra Stack di chiamate, operazione che non abbiamo eseguito in questa procedura dettagliata, è possibile fare clic con il pulsante destro del mouse sul gruppo Funzioni de-ottimizzate e selezionare Elimina per ripristinare solo le funzioni nel gruppo allo stato ottimizzato.

    Screenshot che mostra la finestra Punti di interruzione.

    La finestra Punti di interruzione mostra il gruppo Funzioni deoptimizzate. Il gruppo è selezionato e il menu di scelta rapida è aperto con l'opzione Elimina gruppo di breakpoint selezionata.

Disattivare il debug dinamico C++

Potrebbe essere necessario eseguire il debug di codice ottimizzato senza che venga deoptimizzato o inserire un punto di interruzione nel codice ottimizzato e mantenere ottimizzato il codice quando raggiunge il punto di interruzione. Esistono diversi modi per disattivare il debug dinamico o impedirne la deoptimizzazione del codice quando si raggiunge un punto di interruzione:

  • Nel menu principale di Visual Studio selezionare Opzioni strumenti>. Nel riquadro Opzioni espandere la sezione Tutte le impostazioni>Debug>generale . Deselezionare la casella di controllo Deoptimize debugged functions when possible (.NET 8+, C++ Dynamic Debugging). Al successivo avvio del debugger, il codice rimane ottimizzato.
  • Nel menu principale di Visual Studio selezionare Opzioni strumenti>. Nella finestra di dialogo Opzioni espandere la sezione Debug>generale . Deselezionare la casella di controllo Deoptimize debugged functions when possible (.NET 8+, C++ Dynamic Debugging). Al successivo avvio del debugger, il codice rimane ottimizzato.
  • Molti punti di interruzione del debug dinamico sono due punti di interruzione: uno nel file binario ottimizzato e uno nel file binario non ottimizzato. Nella finestra Punti di interruzione selezionare Mostrafunzione>. Cancellare il punto di interruzione associato al file binario alt . L'altro punto di interruzione nella coppia si interrompe nel codice ottimizzato.
  • Quando si esegue il debug, nel menu principale di Visual Studio selezionare Debug>disassembly>. Assicurarsi che abbia lo stato attivo. Quando si entra in una funzione tramite la finestra Disassembly, la funzione non verrà deottimizzata.
  • Disabilitare completamente il debug dinamico non passando /dynamicdeopt a cl.exe, lib.exee link.exe. Se si usano librerie di terze parti e non è possibile ricompilarle, non passare /dynamicdeopt durante la fase finale link.exe per disabilitare il debug dinamico per il file binario.
  • Per disabilitare rapidamente il debug dinamico per un singolo file binario (ad esempio, test.dll), rinominare o eliminare il alt file binario (ad esempio, test.alt.dll).
  • Per disabilitare il debug dinamico per uno o più .cpp file, non passare /dynamicdeopt durante la compilazione. Il resto del progetto viene compilato con il debug dinamico.

Abilitare il debug dinamico C++ per Unreal Engine 5.6 o versione successiva

Unreal Engine 5.6 supporta il debug dinamico C++ sia per lo strumento di compilazione Unreal che per l'acceleratore di compilazione Unreal. Esistono due modi per abilitarlo. Modificare il BuildConfiguration.xml file o Modificare il Targets.cs file.

Modificare il BuildConfiguration.xml file

In Visual Studio selezionare la configurazione dell'Editor di sviluppo e modificare BuildConfiguration.xml per includere <bDynamicDebugging>true</bDynamicDebugging>. Per altre informazioni su e sulla relativa posizione, vedere Build Configuration.For more information about BuildConfiguration.xml and its location, see Build Configuration.

  1. Un modo per individuare il BuildConfiguration.xml file consiste nell'eseguire una compilazione e controllare l'output del log di compilazione. Ad esempio, quando si compila il gioco di Lyra Starter, viene visualizzato un output simile al seguente:

    - 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. Log.txtCerca BuildConfiguration.xml. Deve contenere una riga come Reading configuration file from: C:\LyraStarterGame\Saved\UnrealBuildTool\BuildConfiguration.xml

  3. Modificare il file in modo che BuildConfiguration.xml contenga <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>
    

Modificare il Targets.cs file

L'altro modo per abilitare il debug dinamico C++ sia per lo strumento di compilazione Unreal che per l'acceleratore di compilazione Unreal consiste nel modificare il Target.cs file in modo che contenga WindowsPlatform.bDynamicDebugging = true.

I progetti unreal Engine hanno Target.cs file associati a diversi tipi di destinazione, tra cui:

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

Per una compilazione dell'editor nel file {ProjectName}Editor.Target.cs, aggiungere WindowsPlatform.bDynamicDebugging = true; al costruttore.

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

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

Oppure, per una compilazione di gioco, nel file {ProjectName}.Target.cs, aggiungere 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...
}

Per altre informazioni sui file di destinazione del motore Unreal, vedere Destinazioni.

Abilitare il debug dinamico C++ per Unreal Engine 5.5 o versioni precedenti

Per Unreal Engine 5.5 o versioni precedenti, applica tramite cherry-pick le modifiche dello Unreal Build Tool dal GitHub nel tuo repository.

Annotazioni

Per accedere ai repository Epic in GitHub, è necessario un account Epic e un account GitHub registrato.

Dopo aver selezionato le modifiche da applicare al repository, abilitare bDynamicDebugging come descritto in precedenza. È anche necessario usare Unreal Build Accelerator da Unreal Engine 5.6. Usare i bit più recenti da ue5-main o disabilitare UBA aggiungendo quanto segue a BuildConfiguration.xml:

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

Per altre informazioni sulla configurazione della compilazione di Unreal Engine, vedere Build Configuration.

Risoluzione dei problemi

Se i punti di interruzione non vengono raggiunti nelle funzioni deoptimizzate:

  • Se si esce da un [Deoptimized] frame, è possibile che si trovi nel codice ottimizzato, a meno che il chiamante non sia stato deottimizzato a causa di un punto di interruzione in esso contenuto o se si è passati al chiamante mentre si raggiunge la funzione corrente.

  • Assicurarsi che i file alt.exe e alt.pdb siano stati compilati. Per test.exe e test.pdbtest.alt.exe e test.alt.pdb devono esistere nella stessa directory. Assicurarsi che le opzioni di compilazione corrette siano impostate in base a questo articolo.

  • Esiste debug directory una voce in test.exe che il debugger usa per trovare il alt binario da usare per il debug deottimizzato. Aprire un prompt dei comandi nativo x64 di Visual Studio ed eseguire link /dump /headers <your executable.exe> per verificare se esiste una voce deopt. Nella colonna deopt compare una voce Type, come mostrato nell'ultima riga di questo esempio:

      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 la deopt voce della directory di debug non è presente, verificare di passare /dynamicdeopt a cl.exe, lib.exe, e link.exe.

  • La deottimizzazione dinamica non funzionerà in modo coerente se /dynamicdeopt non viene passato a cl.exe, lib.exe e link.exe per tutti i .cpp, .lib e i file binari. Verificare che le opzioni appropriate siano impostate quando si compila il progetto.

Per altre informazioni sui problemi noti, vedere Debug dinamico C++: debug completo per le compilazioni ottimizzate.

Se le cose non funzionano come previsto, aprire un ticket in Developer Community. Includere il maggior numero possibile di informazioni sul problema.

Note generali

IncrediBuild 10.24 supporta le compilazioni di debug dinamico C++.
FastBuild v1.15 supporta le compilazioni di debug dinamico C++.

Le funzioni inline vengono deottimizzate su richiesta. Se si imposta un punto di interruzione su una funzione in linea, il debugger deottimizza la funzione e il suo chiamante. Il punto di interruzione raggiunge dove previsto, come se il programma fosse stato compilato senza ottimizzazioni del compilatore.

Una funzione rimane deoptimizzata anche se si disabilitano i punti di interruzione al suo interno. Per ripristinare lo stato ottimizzato, è necessario rimuovere il punto di interruzione per la funzione.

Molti punti di interruzione del debug dinamico sono due punti di interruzione: uno nel file binario ottimizzato e uno nel file binario non ottimizzato. Per questo motivo, nella finestra Punti di interruzione vengono visualizzati più punti di interruzione .

I flag del compilatore usati per la versione deoptimizzata sono gli stessi dei flag usati per la versione ottimizzata, ad eccezione dei flag di ottimizzazione e /dynamicdeopt. Questo comportamento significa che tutti i flag impostati per definire le macro e così via vengono impostati anche nella versione deoptimizzata.

Il codice deoptimizzato non è uguale al codice di debug. Il codice deoptimizzato viene compilato con gli stessi flag di ottimizzazione della versione ottimizzata, quindi asserzioni e altro codice che si basano su impostazioni specifiche del debug non sono inclusi.

Integrazione del sistema di build

Il debug dinamico C++ richiede che i flag del compilatore e del linker siano impostati in modo specifico. Le sezioni seguenti descrivono come configurare una configurazione dedicata per il debug dinamico che non dispone di opzioni in conflitto.

Se il progetto viene compilato con il sistema di compilazione di Visual Studio, un buon modo per eseguire una configurazione di debug dinamico consiste nell'usare Configuration Manager per clonare la configurazione di rilascio o debug e apportare modifiche per supportare il debug dinamico. Nelle due sezioni seguenti vengono descritte le procedure.

Creare una nuova configurazione di versione

  1. Nel menu principale di Visual Studio selezionare Compila>Configuration Manager per aprire Configuration Manager.

  2. Selezionare l'elenco a discesa Configurazione e quindi selezionare <Nuovo.>

    Una screenshot che mostra Configuration Manager.

    In Configuration Manager, in Contesti di progetto, l'elenco a discesa Configurazione è aperto ed è evidenziato.

  3. Verrà visualizzata la finestra di dialogo Nuova configurazione soluzione . Nel campo Nome immettere un nome per la nuova configurazione, ad esempio ReleaseDD. Assicurarsi che l'opzione Copia le impostazioni da: sia impostata su Release. Selezionare quindi OK per creare la nuova configurazione.

    Screenshot che mostra la finestra di dialogo Nuova configurazione progetto per una versione di rilascio.

    Il campo Nome è impostato su ReleaseDD. L'elenco a discesa 'Copia impostazioni da' è impostato su Rilascio.

  4. La nuova configurazione viene visualizzata nell'elenco a discesa Configurazione soluzione attiva . Seleziona Chiudi.

  5. Con l'elenco a discesa Configurazione impostato su ReleaseDD, fare clic con il pulsante destro del mouse sul progetto in Esplora soluzioni e selezionare Proprietà.

  6. In Proprietà di configurazione>Avanzate, impostare Usa debug dinamico C++ su .

  7. Assicurarsi che l'intera ottimizzazione programma sia impostata su No.

    Screenshot che mostra le proprietà avanzate del progetto.

    La pagina delle proprietà viene aperta in Proprietà di configurazione > Avanzate. Usare il debug dinamico C++. La proprietà è impostata su Sì. L'intera ottimizzazione del programma è impostata su No.

  8. In proprietà di configurazione>linker>ottimizzazione, assicurarsi che Abilita riduzione COMDAT sia impostata su No (/OPT:NOICF).

    Screenshot che mostra le proprietà del progetto di ottimizzazione del linker.

    La pagina delle proprietà viene aperta in Proprietà di configurazione > Linker > Ottimizzazione > Abilita riduzione CMDAT. La proprietà è impostata su No (/OPT:NOICF).

Questa impostazione aggiunge l'opzione /dynamicdeopt al compilatore e al linker. Con i commutatori /GL di ottimizzazione C++ e /OPT:ICF anche disattivati, è ora possibile compilare ed eseguire il progetto nella nuova configurazione quando si vuole una build di versione ottimizzata che è possibile usare con il debug dinamico C++.

È possibile aggiungere altre opzioni usate con le build di vendita al dettaglio a questa configurazione in modo che siano sempre attivate o disattivate esattamente le opzioni previste quando si usa il debug dinamico. Per altre informazioni sulle opzioni che non è consigliabile usare con il debug dinamico, vedere Opzioni incompatibili.

Per altre informazioni sulle configurazioni in Visual Studio, vedere Creare e modificare le configurazioni.

Creare una nuova configurazione di debug

Se si desidera usare i file binari di debug, ma si vuole che vengano eseguiti più velocemente, è possibile modificare la configurazione di debug.

  1. Nel menu principale di Visual Studio selezionare Compila>Configuration Manager per aprire Configuration Manager.

  2. Selezionare l'elenco a discesa Configurazione e quindi selezionare <Nuovo.>

    Una screenshot che mostra Configuration Manager.

    In Configuration Manager, nella sezione Contesti progetto della finestra, l'elenco a discesa Configurazione è aperto e è evidenziato.

  3. Verrà visualizzata la finestra di dialogo Nuova configurazione progetto . Nel campo Nome immettere un nome per la nuova configurazione, ad esempio DebugDD. Assicurarsi che l'opzione Copia le impostazioni da: sia impostata su Debug. Selezionare quindi OK per creare la nuova configurazione.

    Screenshot che mostra la finestra di dialogo

    Il campo nome è impostato su DebugDD. L'elenco a discesa Copia impostazioni da: è impostato su Debug.

  4. La nuova configurazione viene visualizzata nell'elenco a discesa Configurazione soluzione attiva . Seleziona Chiudi.

  5. Con l'elenco a discesa Configurazione impostato su DebugDD, fare clic con il pulsante destro del mouse sul progetto in Esplora soluzioni e scegliere Proprietà.

  6. In Proprietà> di configurazioneC/C++>Ottimizzazione attivare le ottimizzazioni desiderate. Ad esempio, è possibile impostare Ottimizzazione su Ottimizza velocità (/O2).

  7. In Generazione di codice>, imposta i Controlli di runtime di base su Impostazione predefinita.

  8. In C/C++>Generale, disabilita Debug Solo Mio Codice.

  9. Impostare Formato informazioni di debug su Database programma (/Zi).Set Debug Information Format to Program Database (/Zi).

È possibile aggiungere altre opzioni usate con le compilazioni di debug a questa configurazione in modo che siano sempre attivate o disattivate esattamente le opzioni previste quando si usa il debug dinamico. Per altre informazioni sulle opzioni che non è consigliabile usare con il debug dinamico, vedere Opzioni incompatibili.

Per altre informazioni sulle configurazioni in Visual Studio, vedere Creare e modificare le configurazioni.

Considerazioni sul sistema di compilazione personalizzato

Se si dispone di un sistema di compilazione personalizzato, assicurarsi di:

  • Passare /dynamicdeopt a cl.exe, lib.exe e link.exe.
  • Non usare /ZI, nessuno dei /RTC flag o /JMC.

Per i distributori di build:

  • Per un progetto denominato test, il compilatore produce test.alt.obj, test.alt.exp, test.obje test.exp. Il linker produce test.alt.exe, test.alt.pdbtest.exe, e test.pdb.
  • È necessario distribuire il nuovo file binario c2dd.dll del set di strumenti insieme a c2.dll.

Opzioni incompatibili

Alcune opzioni del compilatore e del linker non sono compatibili con il debug dinamico C++. Se si attiva il debug dinamico C++ usando le impostazioni del progetto di Visual Studio, le opzioni incompatibili vengono disattivate automaticamente, a meno che non vengano impostate specificamente nell'impostazione delle opzioni della riga di comando aggiuntive.

Le opzioni del compilatore seguenti non sono compatibili con il debug dinamico 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

Le opzioni del linker seguenti non sono compatibili con il debug dinamico C++:

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

Vedere anche

Flag del compilatore /dynamicdeopt (anteprima)
Flag del linker /DYNAMICDEOPT (versione di anteprima)
Debug dinamico C++: debug completo per le compilazioni ottimizzate
Eseguire il debug di codice ottimizzato