Freigeben über


Dynamisches Debuggen von C++ (Vorschau)

Wichtig

Das dynamische Debuggen von C++ befindet sich derzeit in der Vorschau. Diese Informationen beziehen sich auf ein Vorabversionsfeature, das vor der Veröffentlichung erheblich geändert werden kann. Microsoft übernimmt keine Gewährleistungen, ausgedrückt oder impliziert, in Bezug auf die hier bereitgestellten Informationen.

Dieses Vorschaufeature ab Visual Studio 2022, Version 17.14 Preview 2, gilt nur für x64-Projekte.

Mit dem dynamischen Debuggen von C++ können Sie optimierten Code so debuggen, als wäre er nicht optimiert. Dieses Feature ist nützlich für Entwickler, die die Leistungsvorteile von optimiertem Code benötigen, z. B. Spieleentwickler, die hohe Frameraten benötigen. Mit dem dynamischen Debuggen von C++ können Sie das Debuggen von nicht optimierten Code genießen, ohne die Leistungsvorteile optimierter Builds zu beeinträchtigen.

Das Debuggen optimierter Code stellt Herausforderungen dar. Der Compiler positioniert und organisiert Anweisungen, um Code zu optimieren. Das Ergebnis ist effizienterer Code, bedeutet aber:

  • Der Optimierer kann lokale Variablen entfernen oder an unbekannte Speicherorte für den Debugger verschieben.
  • Code innerhalb einer Funktion wird möglicherweise nicht mehr am Quellcode ausgerichtet, wenn der Optimierer Codeblöcke zusammenführt.
  • Funktionsnamen für Funktionen im Aufrufstapel sind möglicherweise falsch, wenn der Optimierer zwei Funktionen zusammenführt.

In der Vergangenheit behandelten Entwickler diese Probleme und andere, als sie sich beim Debuggen von optimiertem Code befanden. Jetzt werden diese Herausforderungen beseitigt, weil Sie mit dem dynamischen Debuggen von C++ in optimierten Code eintreten können, als wäre er nicht optimiert.

Zusätzlich zum Generieren der optimierten Binärdateien generiert das Kompilieren mit /dynamicdeopt nicht optimierte Binärdateien, die beim Debuggen verwendet werden. Wenn Sie einen Haltepunkt hinzufügen oder in eine Funktion einsteigen (einschließlich __forceinline-Funktionen), lädt der Debugger die unoptimierte Binärdatei. Anschließend können Sie den nicht optimierten Code für die Funktion anstelle des optimierten Codes debuggen. Sie können debuggen, als ob Sie nicht optimierten Code debuggen, während Sie weiterhin die Leistungsvorteile von optimiertem Code im restlichen Programm erhalten.

Testen des dynamischen Debuggens von C++

Sehen wir uns zunächst an, wie es ist, optimierte Code zu debuggen. Anschließend können Sie sehen, wie das dynamische Debuggen von C++ den Prozess vereinfacht.

  1. Erstellen Sie ein neues C++-Konsolenanwendungsprojekt in Visual Studio. Ersetzen Sie den Inhalt der datei ConsoleApplication.cpp durch den folgenden Code:

    // 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. Bitte ändern Sie die Dropdownliste Lösungskonfigurationen zu Release. Stellen Sie sicher, dass die Dropdownliste der Lösungsplattform auf x64-festgelegt ist.

  3. Führen Sie eine neue Erstellung durch, indem Sie Erstellen>Projektmappe neu erstellen auswählen.

  4. Legen Sie einen Breakpoint bei Zeile 55 fest, int neighbors = countNeighbors(grid, i, j); in updateGrid(). Führen Sie das Programm aus.

  5. Wenn Sie den Breakpoint erreichen, sehen Sie sich das Fenster Lokal. Wählen Sie im Hauptmenü Debug>Windows>Localsaus. Beachten Sie, dass der Wert von i oder j im Locals Fenster nicht angezeigt wird. Der Compiler hat sie wegoptimiert.

  6. Versuchen Sie, einen Breakpoint bei Zeile 19 festzulegen, cout << (grid[i][j] ? '*' : ' '); in printGrid(). Dies ist nicht möglich. Dieses Verhalten wird erwartet, da der Compiler den Code optimiert hat.

Beenden Sie das Programm, und aktivieren Sie das dynamische Debuggen von C++ und versuchen Sie es erneut.

  1. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, und wählen Sie Eigenschaften aus, um die Eigenschaftenseiten für das Projekt zu öffnen.

  2. Wählen Sie Advanced>Use C++ Dynamic Debuggingund ändern Sie die Einstellung zu Ja.

    Ein Screenshot, der die erweiterten Projekteigenschaften zeigt.

    Die Eigenschaftenseite öffnet sich unter Konfigurationseigenschaften > Erweitert > Verwenden des dynamischen Debuggings von C++. Die Eigenschaft ist auf „Ja” festgelegt.

    In diesem Schritt wird der /dynamicdeopt Switch zum Compiler und zum Linker hinzugefügt. Hinter den Kulissen werden auch die C++-Optimierungsschalter /GL und /OPT:ICFdeaktiviert. Diese Einstellung überschreibt keine Schalter, die Sie manuell zur Befehlszeile oder anderen festgelegten Optimierungsschaltern hinzugefügt haben, z. B. /O1.

  3. Führen Sie eine neue Erstellung durch, indem Sie Erstellen>Projektmappe neu erstellen auswählen. Build-Diagnosecode MSB8088 erscheint, was darauf hinweist, dass dynamisches Debugging und die Optimierung des gesamten Programms inkompatibel sind. Dieser Fehler bedeutet, dass die gesamte Programmoptimierung (/GL) während der Kompilierung automatisch deaktiviert wurde.

    Sie können die gesamte Programmoptimierung in den Projekteigenschaften manuell deaktivieren. Wählen Sie Konfigurationseigenschaften>Erweitert>Ganze Programmoptimierung aus, und ändern Sie die Einstellung in Aus. Jetzt wird MSB8088 als Warnung behandelt, kann aber in einer zukünftigen Version von Visual Studio als Fehler behandelt werden.

  4. Führen Sie die App erneut aus.

    Wenn Sie nun in Zeile 55 auf den Breakpoint klicken, werden die Werte von i und j im Fenster Lokal angezeigt. Im Fenster Aufrufstapel wird angezeigt, dass updateGrid() deoptimiert ist und der Dateiname life.alt.exelautet. Diese alternative Binärdatei wird verwendet, um optimierten Code zu debuggen.

    Ein Screenshot, der das Debuggen der UpdateGrid-Funktion zeigt.

    Ein Breakpoint wird in der Funktion updateGrid angezeigt. Der Aufrufstapel zeigt an, dass die Funktion deoptimiert ist und der Dateiname life.alt.exeist. Im Fenster "Lokal" werden die Werte von i und j und die anderen lokalen Variablen in der Funktion angezeigt.

    Die updateGrid()-Funktion wird bei Bedarf deoptimiert, da Sie einen Haltepunkt darin festgelegt haben. Wenn Sie beim Debuggen eine optimierte Funktion durchlaufen, wird sie nicht deoptimiert. Wenn Sie in eine Funktion eintreten, wird sie deoptimiert. Die wichtigste Möglichkeit, eine Funktion zu deoptimieren, besteht darin, einen Haltepunkt darin festzulegen oder in sie hineinzugehen.

    Sie können eine Funktion auch im Fenster Aufrufliste deoptimieren. Klicken Sie mit der rechten Maustaste auf die Funktion oder eine ausgewählte Gruppe von Funktionen, und wählen Sie Beim nächsten Aufruf deoptimieren aus. Dieses Feature ist nützlich, wenn Sie lokale Variablen in einer optimierten Funktion anzeigen möchten, für die Sie keinen Haltepunkt an anderer Stelle im Aufrufstapel festgelegt haben. Funktionen, die auf diese Weise deoptimiert sind, werden im Fenster Breakpoints als Breakpointgruppe mit dem Namen Deoptimierte Funktionen gruppiert. Wenn Sie die Haltepunktgruppe löschen, werden die zugehörigen Funktionen auf ihren optimierten Zustand zurückgesetzt.

Verwenden von bedingten und abhängigen Breakpoints

  1. Versuchen Sie erneut, einen Breakpoint in Zeile 19 festzulegen, cout << (grid[i][j] ? '*' : ' '); in printGrid(). Jetzt funktioniert es. Wenn Sie einen Haltepunkt in der Funktion festlegen, wird die Funktion deoptimiert, sodass Sie sie normal debuggen können.

  2. Klicken Sie mit der rechten Maustaste auf den Haltepunkt in Zeile 19, wählen Sie Bedingungenaus, und legen Sie die Bedingung auf i == 10 && j== 10fest. Aktivieren Sie dann das Kontrollkästchen Nur aktivieren, wenn der folgende Breakpoint erreicht wird:. Wählen Sie den Haltepunkt in Zeile 55 aus der Dropdownliste aus. Nun wird der Breakpoint in Zeile 19 erst dann erreicht, wenn der Breakpoint in Zeile 50 zuerst erreicht wird und dann, wenn grid[10][10] kurz davor ist, in die Konsole auszugeben.

    Der Punkt besteht darin, dass Sie bedingte und abhängige Haltepunkte in einer optimierten Funktion festlegen und lokale Variablen und Codezeilen verwenden können, die in einem optimierten Build für den Debugger möglicherweise nicht verfügbar sind.

    Ein Screenshot, der die Einstellungen für einen bedingten Haltepunkt für Zeile 19 zeigt.

    Ein bedingter Breakpoint wird in Zeile 19 angezeigt, cout < < (grid[i][j] ? '*' : ' ');. Die Bedingung ist auf i == 10 && j == 10 festgelegt. Das Kontrollkästchen „Nur aktivieren, wenn der folgende Breakpoint erreicht wird” ist aktiviert. Die Dropdownliste für Breakpoints ist auf life.cpp Zeile 55 festgelegt.

  3. Fahren Sie mit der Ausführung der App fort. Wenn der Haltepunkt in Zeile 19 erreicht ist, können Sie mit der rechten Maustaste auf Zeile 15 klicken und Nächste Anweisung festlegen auswählen, um die Schleife erneut auszuführen.

    Ein Screenshot, der das Debuggen der printGrid-Funktion zeigt.

    Ein bedingter und abhängiger Breakpoint wird in Zeile 19 erreicht, cout < < (grid[i][j] ? '*' : ' ');. Im Fenster "Lokal" werden die Werte von i und j und die anderen lokalen Variablen in der Funktion angezeigt. Im Fenster "Aufrufstapel" wird angezeigt, dass die Funktion deoptimiert ist und der Dateiname life.alt.exelautet.

  4. Löschen Sie alle Haltepunkte, um deoptimierte Funktionen in ihren optimierten Zustand zurückzuführen. Wählen Sie im Visual Studio-Hauptmenü Debuggen>Alle Haltepunkte löschen aus. Alle Funktionen kehren dann zum optimierten Zustand zurück.

    Wenn Sie Breakpoints über das Fenster Aufrufliste und die Option Beim nächsten Eintrag deoptimieren hinzufügen, was wir in dieser exemplarischen Vorgehensweise nicht getan haben, können Sie mit der rechten Maustaste auf die Gruppe Deoptimierte Funktionen klicken und Löschen auswählen, um nur die Funktionen in dieser Gruppe wieder in ihren optimierten Zustand zurückzuversetzen.

    Ein Screenshot, der das Fenster

    Im Fenster "Haltepunkte" wird die Gruppe "Deoptimisierte Funktionen" angezeigt. Die Gruppe ist ausgewählt, und das Kontextmenü wird mit der Option „Breakpointgruppe löschen” geöffnet.

Deaktivieren des dynamischen Debuggens von C++

Möglicherweise müssen Sie optimierten Code debuggen, ohne dass er deoptimiert wird, oder einen Haltepunkt in optimierten Code setzen und der Code optimiert bleibt, wenn der Haltepunkt erreicht wird. Es gibt mehrere Möglichkeiten, dynamisches Debuggen zu deaktivieren oder den Code am Deoptimieren zu hindern, wenn ein Breakpoint erreicht wird.

  • Wählen Sie im Hauptmenü von Visual Studio Extras>Optionen>Debuggen>Allgemein aus. Deaktivieren Sie das Kontrollkästchen „Debuggierte Funktionen automatisch deoptimieren, wenn möglich“ (.NET 8+, C++-dynamisches Debuggen). Wenn der Debugger das nächste Mal gestartet wird, bleibt der Code optimiert.
  • Viele dynamische Debugging-Haltepunkte sind zwei Haltepunkte: eine in der optimierten Binärdatei und eine in der nicht optimierten Binärdatei. Wählen Sie im Fenster Breakpoints die Option Spalten anzeigen>Funktion aus. Löschen Sie den Breakpoint, der der alt-Binärdatei zugeordnet ist. Der andere Breakpoint in den Paaren bricht im optimierten Code.
  • Wenn Sie debuggen, wählen Sie im Hauptmenü von Visual Studio Debuggen>Windows>Disassemblyaus. Stellen Sie sicher, dass er den Fokus hat. Wenn Sie eine Funktion über das Disassembly-Fenster aufrufen, wird die Funktion nicht deoptimiert.
  • Deaktivieren Sie das dynamische Debuggen vollständig, indem Sie /dynamicdeopt nicht an cl.exe, lib.exeund link.exeübergeben. Wenn Sie Bibliotheken von Drittanbietern verwenden und diese nicht neu erstellen können, übergeben Sie /dynamicdeopt nicht während des letzten Schritts link.exe, um das dynamische Debugging für diese Binärdatei zu deaktivieren.
  • Um dynamisches Debuggen für eine einzelne Binärdatei (z. B. test.dll) schnell zu deaktivieren, benennen oder löschen Sie die alt Binärdatei (z. B. test.alt.dll).
  • Um das dynamische Debuggen für eine oder mehrere .cpp-Dateien zu deaktivieren, übergeben Sie beim Erstellen nicht /dynamicdeopt. Der rest des Projekts wird mit dem dynamischen Debuggen erstellt.

Aktivieren des dynamischen Debuggens von C++ im Unreal Engine

Unreal Engine 5.6 unterstützt das dynamische C++-Debugging für unreal Build Tool und Unreal Build Accelerator. Es gibt zwei Möglichkeiten zum Aktivieren:

  • Ändern Sie die Target.cs Datei Ihres Projekts so, dass sie WindowsPlatform.bDynamicDebugging = trueenthält.

  • Verwenden Sie die Konfiguration des Entwicklungs-Editors, und ändern Sie BuildConfiguration.xml, um Folgendes hinzuzufügen:

    <WindowsPlatform>
        <bDynamicDebugging>true</bDynamicDebugging>
    </WindowsPlatform>
    

Für Unreal Engine 5.5 oder früher, wählen und übernehmen Sie die Änderungen des Unreal Build Tools aus GitHub in Ihr Repository. Aktivieren Sie dann bDynamicDebugging wie oben angegeben. Sie müssen auch unreal Build Accelerator von Unreal Engine 5.6 verwenden. Verwenden Sie entweder die neuesten Bits aus ue5-main, oder deaktivieren Sie UBA, indem Sie folgendes zu BuildConfiguration.xmlhinzufügen:

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

Weitere Informationen zur Konfiguration des Builds der Unreal Engine finden Sie unter Build-Konfiguration.

Problembehandlung

Wenn Breakpoints in deoptimierten Funktionen nicht erreicht werden:

  • Wenn Sie aus einem [Deoptimized]-Frame heraustreten, befinden Sie sich möglicherweise in optimiertem Code, es sei denn, der Aufrufer wurde aufgrund eines Haltepunkts darin deoptimiert oder Sie sind auf dem Weg zur aktuellen Funktion in den Aufrufer eingetreten.

  • Stellen Sie sicher, dass die Dateien alt.exe und alt.pdb erstellt wurden. Für test.exe und test.pdbmüssen test.alt.exe und test.alt.pdb im selben Verzeichnis vorhanden sein. Stellen Sie sicher, dass die richtigen Build-Einstellungen gemäß diesem Artikel festgelegt sind.

  • In debug directory ist ein test.exe-Eintrag vorhanden, den der Debugger verwendet, um die alt-Binärdatei für das deoptimierte Debuggen zu finden. Öffnen Sie eine x64-native Visual Studio-Eingabeaufforderung, und führen Sie link /dump /headers <your executable.exe> aus, um festzustellen, ob ein deopt Eintrag vorhanden ist. Ein deopt Eintrag wird in der Spalte Type angezeigt, wie in der letzten Zeile dieses Beispiels dargestellt:

      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
    

    Wenn der deopt Debugverzeichniseintrag nicht vorhanden ist, vergewissern Sie sich, dass Sie /dynamicdeopt an cl.exe, lib.exeund link.exeübergeben.

  • Die dynamische Deoptimierung funktioniert nicht konsistent, wenn /dynamicdeopt nicht an cl.exe, lib.exeund link.exe für alle .cpp, .libund Binärdateien übergeben wird. Vergewissern Sie sich, dass die richtigen Schalter festgelegt sind, wenn Sie Ihr Projekt erstellen.

Weitere Informationen zu bekannten Problemen finden Sie unter dynamisches Debuggen von C++: Vollständige Debuggierbarkeit für optimierte Builds.

Wenn die Dinge nicht wie erwartet funktionieren, öffnen Sie ein Ticket bei Developer Community. Fügen Sie so viele Informationen wie möglich zu dem Problem ein.

Allgemeine Hinweise

IncrediBuild 10.24 unterstützt C++-Builds für dynamisches Debuggen.
FastBuild v1.15 unterstützt C++-Builds für dynamisches Debuggen.

Inline-Funktionen werden bei Bedarf deoptimiert. Wenn Sie einen Haltepunkt für eine inlinierte Funktion festlegen, deoptimiert der Debugger die Funktion und deren Aufrufer. Der Breakpoint trifft genau dort, wo Sie es erwarten, als ob Ihr Programm ohne Compileroptimierungen erstellt worden wäre.

Eine Funktion bleibt weiterhin deoptimiert, auch wenn Sie die Breakpoint darin deaktivieren. Sie müssen den Haltepunkt für die Funktion entfernen, um den optimierten Zustand wiederherzustellen.

Viele dynamische Debugging-Haltepunkte sind zwei Haltepunkte: eine in der optimierten Binärdatei und eine in der nicht optimierten Binärdatei. Aus diesem Grund sehen Sie mehr als einen Breakpoint im Fenster Breakpoints.

Die Compiler-Flags, die für die deoptimierte Version verwendet werden, sind identisch mit den Flags, die für die optimierte Version verwendet werden, mit Ausnahme von Optimierungskennzeichnungen und /dynamicdeopt. Dieses Verhalten bedeutet, dass alle Flags, die Sie zum Definieren von Makros festgelegt haben, auch in der deoptimierten Version festgelegt werden.

Deoptimierter Code entspricht nicht dem Debugcode. Der deoptimierte Code wird mit den gleichen Optimierungskennzeichnungen wie die optimierte Version kompiliert, sodass assertions und anderer Code, der auf debugspezifischen Einstellungen basiert, nicht enthalten ist.

Erstellen der Systemintegration

Für das dynamische Debuggen von C++ müssen Compiler- und Linker-Flags in einer bestimmten Weise gesetzt werden. In den folgenden Abschnitten wird beschrieben, wie Sie eine spezielle Konfiguration für dynamisches Debugging einrichten, bei der keine Konflikte zwischen den Schaltern auftreten.

Wenn Ihr Projekt mit dem Visual Studio-Buildsystem erstellt wird, empfiehlt es sich, eine Konfiguration für dynamisches Debuggen mithilfe von Configuration Manager zu erstellen, um Ihre Release- oder Debugkonfiguration zu klonen und Änderungen vorzunehmen, um dynamisches Debuggen aufzunehmen. In den folgenden beiden Abschnitten werden die Verfahren beschrieben.

Erstellen einer neuen Releasekonfiguration

  1. Wählen Sie im Hauptmenü von Visual Studio unter Build>den Configuration Manager aus, um den Configuration Manager zu öffnen.

  2. Wählen Sie die Dropdownliste Konfiguration und dann <Neu...> aus.

    Ein Screenshot, der Configuration Manager zeigt.

    In Configuration Manager ist unter Project-Kontexten die Dropdownliste "Konfiguration" geöffnet, und ist hervorgehoben.

  3. Das Dialogfeld Neue Lösungskonfiguration wird geöffnet. Geben Sie im Feld Name einen Namen für die neue Konfiguration ein, z. B. ReleaseDD. Stellen Sie sicher, dass Einstellungen kopieren von: auf Freigabe festgelegt ist. Wählen Sie dann OK aus, um die neue Konfiguration zu erstellen.

    Screenshot des Dialogfelds

    Das Feld "Name" ist auf "ReleaseDD" festgelegt. Die Dropdown-Liste ‚Einstellungen kopieren von‘ ist auf Freigeben festgelegt.

  4. Die neue Konfiguration wird in der Dropdownliste Aktiven Lösungskonfiguration angezeigt. Wählen Sie Schließen aus.

  5. Wenn die Dropdownliste Konfiguration auf ReleaseDD festgelegt ist, klicken Sie mit der rechten Maustaste auf Ihr Projekt im Projektmappen-Explorer, und wählen Sie Eigenschaften aus.

  6. Legen Sie unter Konfigurationseigenschaften>Erweitert die Option Dynamisches Debuggen von C++ verwenden auf Ja fest.

  7. Stellen Sie sicher, dass Optimierung des gesamten Programms auf Nein festgelegt ist.

    Ein Screenshot, der die erweiterten Projekteigenschaften zeigt.

    Die Eigenschaftenseite wird mit „Konfigurationseigenschaften” > „Erweitert” geöffnet. Verwenden Sie das dynamische Debuggen von C++. Die Eigenschaft ist auf „Ja” festgelegt. „Optimierung des gesamten Programms” ist auf „Nein” festgelegt.

  8. Stellen Sie unter Konfigurationseigenschaften>Linker>Optimierung sicher, dass COMDAT-Faltung aktivieren auf Nein (/OPT:NOICF) festgelegt ist.

    Ein Screenshot, der die Projekteigenschaften der Linker-Optimierung zeigt.

    Die Eigenschaftenseite wird mit „Konfigurationseigenschaften” > „Linker” > „Optimierung” > „CMDAT-Faltung aktivieren” geöffnet. Die Eigenschaft ist auf „Nein (/OPT:NOICF)” festgelegt.

Diese Einstellung fügt den /dynamicdeopt Switch zum Compiler und zum Linker hinzu. Mit C++-Optimierungsschaltern /GL und /OPT:ICF auch deaktiviert, können Sie ihr Projekt jetzt in der neuen Konfiguration erstellen und ausführen, wenn Sie einen optimierten Releasebuild benötigen, den Sie mit dem dynamischen Debuggen von C++ verwenden können.

Sie können dieser Konfiguration weitere Schalter hinzufügen, die Sie mit Ihren Produktions-Builds verwenden, damit Sie immer genau die gewünschten Schalter aktivieren oder deaktivieren, die Sie bei Verwendung des dynamischen Debuggings erwarten. Weitere Informationen zu Schaltern, die Sie nicht mit dynamischem Debuggen verwenden sollten, finden Sie unter Inkompatible Optionen.

Weitere Informationen zu Konfigurationen in Visual Studio finden Sie unter Erstellen und Bearbeiten von Konfigurationen.

Erstellen einer neuen Debugkonfiguration

Wenn Sie Debug-Binärdateien verwenden möchten, diese aber schneller ausgeführt werden sollen, können Sie die Debugkonfiguration ändern.

  1. Wählen Sie im Hauptmenü von Visual Studio unter Build>den Configuration Manager aus, um den Configuration Manager zu öffnen.

  2. Wählen Sie die Dropdownliste Konfiguration und dann <Neu...> aus.

    Ein Screenshot, der Configuration Manager zeigt.

    Im Configuration Manager ist im Projektkontextteil des Fensters die Dropdownliste "Konfiguration" geöffnet, und ist hervorgehoben.

  3. Das Dialogfeld Neue Projektkonfiguration wird geöffnet. Geben Sie im Feld Name einen Namen für die neue Konfiguration ein, z. B. DebugDD-. Stellen Sie sicher, dass Einstellungen kopieren von: auf Debuggen festgelegt ist. Wählen Sie dann OK aus, um die neue Konfiguration zu erstellen.

    Screenshot des Dialogfelds

    Das Namensfeld ist auf "DebugDD" festgelegt. Die Dropdownliste „Einstellungen kopieren von:” ist auf „Debuggen” festgelegt.

  4. Die neue Konfiguration wird in der Dropdownliste Aktiven Lösungskonfiguration angezeigt. Wählen Sie Schließen aus.

  5. Wenn die Dropdownliste Konfiguration auf DebugDD festgelegt ist, klicken Sie mit der rechten Maustaste auf Ihr Projekt im Projektmappen-Explorer, und wählen Sie Eigenschaften aus.

  6. Aktivieren Sie in Konfigurationseigenschaften>C/C++>Optimierungdie gewünschten Optimierungen. Sie können z. B. Optimierung auf Geschwindigkeit maximieren (/O2) festlegen.

  7. Legen Sie in C/C++>CodegenerierungGrundlegende Laufzeitüberprüfungen auf Standard fest.

  8. Deaktivieren Sie in C/C++>Allgemein die Option Debuggen von Nur eigenen Code unterstützen.

  9. Legen Sie Debuginformationsformat auf Programmdatenbank (/Zi) fest.

Sie können dieser Konfiguration weitere Optionen hinzufügen, die Sie mit Ihren Debugbuilds verwenden, sodass Sie immer genau die Schalter aktiviert oder deaktiviert haben, die Sie erwarten, wenn Sie dynamisches Debuggen verwenden. Weitere Informationen zu Schaltern, die Sie nicht mit dynamischem Debuggen verwenden sollten, finden Sie unter Inkompatible Optionen.

Weitere Informationen zu Konfigurationen in Visual Studio finden Sie unter Erstellen und Bearbeiten von Konfigurationen.

Überlegungen zum benutzerdefinierten Buildsystem

Wenn Sie über ein benutzerdefiniertes Buildsystem verfügen, stellen Sie sicher, dass Sie:

  • Übergeben Sie /dynamicdeopt an cl.exe, lib.exeund link.exe.
  • Verwenden Sie keines der /ZI, /RTC-Flaggen oder /JMC.

Für Builddistibutor:

  • Für ein Projekt mit dem Namen testerzeugt der Compiler test.alt.obj, test.alt.exp, test.objund test.exp. Der Linker erzeugt test.alt.exe, test.alt.pdb, test.exe und test.pdb.
  • Sie müssen die neue Tools-Binärdatei c2dd.dll zusammen mit c2.dll bereitstellen.

Inkompatible Optionen

Einige Compiler- und Linkeroptionen sind mit dem dynamischen Debuggen von C++ nicht kompatibel. Wenn Sie das dynamische Debuggen mit C++ mithilfe der Visual Studio-Projekteinstellungen aktivieren, werden inkompatible Optionen automatisch deaktiviert, es sei denn, Sie legen sie speziell in der Einstellung für zusätzliche Befehlszeilenoptionen fest.

Die folgenden Compileroptionen sind mit dem dynamischen Debuggen von C++ nicht kompatibel:

/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

Die folgenden Linkeroptionen sind mit dem dynamischen Debuggen von C++ nicht kompatibel:

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

Siehe auch

/dynamicdeopt-Compilerflag (Vorschau)
/DYNAMICDEOPT-Linkerflag (Vorschau)
dynamisches Debuggen von C++: Vollständige Debugbarkeit für optimierte Builds
Optimierten Code debuggen