Freigeben über


Mehrdeutige Haltepunktauflösung

In Version 10.0.25310.1001 und höher des Debuggermoduls wird jetzt die mehrdeutige Auflösung des Haltepunkts unterstützt.

Mehrdeutige Haltepunkte ermöglichen dem Debugger das Setzen von Haltepunkten in bestimmten Szenarien, in denen ein Haltepunktausdruck an mehrere Stellen aufgelöst wird. Dies kann beispielsweise in folgenden Fällen geschehen:

  • Mehrfache Überladungen einer Funktion.
  • Es gibt mehrere Symbole, die einem Haltepunktausdruck entsprechen.
  • Derselbe Symbolname wird für mehrere Speicherorte verwendet.
  • Das Symbol wurde eingebettet.
  • Festlegen eines Haltepunkts in einer Vorlagenfunktion mit mehreren Instanziierungen im Quellfenster.

Wenn diese Option aktiviert ist, legt der Debugger einen Haltepunkt für jede Symbol-Übereinstimmung für einen bestimmten Haltepunktausdruck fest. Der Debugger filtert auch Übereinstimmungen, wenn bestimmte Kriterien erfüllt sind.

Allgemeine Informationen zur Verwendung von Haltepunkten finden Sie unter Verwenden von Haltepunkten.

Aktivieren der Auflösung mehrdeutiger Haltepunkte

Standardmäßig sind mehrdeutige Haltepunkte deaktiviert. Führen Sie diesen Befehl in der WinDbg-Konsole aus, um dies in einer Debuggersitzung zu aktivieren:

dx @$debuggerRootNamespace.Debugger.Settings.EngineInitialization.ResolveAmbiguousBreakpoints = true;

So bestätigen Sie, dass die Einstellung für mehrdeutige Haltepunkte aktiv ist:

0:010> dx @$debuggerRootNamespace.Debugger.Settings.EngineInitialization.ResolveAmbiguousBreakpoints
@$debuggerRootNamespace.Debugger.Settings.EngineInitialization.ResolveAmbiguousBreakpoints                 : true

Weitere Informationen zur Verwendung des Befehls dx finden Sie unter dx (Debugger-Objektmodellausdruck anzeigen).

Wenn Sie die Funktion deaktivieren möchten, legen Sie den oberen Wert auf false fest. Um sicherzustellen, dass die Einstellung über mehrere Sitzungen hinweg erhalten bleibt, klicken Sie auf File -> Settings -> Debugger Settings und aktivieren Sie dann das Kontrollkästchen Persist engine settings across debugger sessions.

Die Verwendung gilt für einzelne Haltepunkte.

Das Auflösen von mehrdeutigen Haltepunktausdrücken gilt nur für die Ausführung des Haltepunktbefehls, um einen einzelnen Haltepunkt im Debugger festzulegen. Das Festlegen mehrerer Haltepunkte mit dem Befehl bm funktioniert also weiterhin wie gewohnt. Das Ausführen des Befehls mit aktiviertem Feature führt zu einem neuen Haltepunktverhalten für einzelne Haltepunkte.

Allgemeine Informationen zu den Haltepunktbefehlen finden Sie unter bp, bu, bm (Haltepunkt festlegen).

Hierarchische Haltepunkte

Hierarchische Haltepunkte stellen das Ergebnis der Auflösung eines mehrdeutigen Haltepunktausdrucks in mehrere Haltepunkte dar. Wenn ein Ausdruck zu zwei oder mehr Übereinstimmungen führt, die zum Festlegen von Haltepunkten verwendet werden, wird ein weiterer Haltepunkt erstellt, der den Haltepunktsatz steuert. Dieser übergeordnete Haltepunkt, der hierarchische Haltepunkt, kann genau wie ein normaler Haltepunkt aktiviert/deaktiviert/gelöscht und aufgelistet werden, mit der zusätzlichen Funktionalität, den gleichen Vorgang für die Haltepunkte auszuführen, die ihm gehören.

Wenn beispielsweise der Befehl bp foo!bar ausgeführt wird, was zu zwei Übereinstimmungen mit dem Symbol barführt, wird ein hierarchischer Haltepunkt erstellt, der die beiden Übereinstimmungen steuert. Wenn die Hierarchie aktiviert/deaktiviert/gelöscht wird, werden auch die übereinstimmenden Haltepunkte aktiviert/deaktiviert/gelöscht.

.bpcmds(Display Breakpoint Commands) listet den Haltepunktbefehl auf, der ausgeführt werden kann, um jeden Haltepunkt festzulegen. Haltepunkte, die einem hierarchischen Haltepunkt gehören, listen weiterhin einen gültigen bp-Befehl auf, der einen Haltepunkt an seiner Adresse setzt. Hierarchische Haltepunkte werden auch in der Ausgabe aufgelistet und zeigen den Befehl an, der verwendet werden kann, um den gesamten Satz von Haltepunkten anstelle eines einzelnen Haltepunkts neu zu erstellen.

Mehrdeutige Symbole

Das Setzen eines Haltepunkts für einen Symbolnamen sollte das folgende Verhalten zur Folge haben, wenn es sich um folgendes Symbol handelt:

  • Eine Überladung: Jede Überladung, die dem Symbol entspricht, sollte einen Haltepunkt haben.

  • Eine Vorlagenfunktion:

    • Wenn für den Ausdruck alle Vorlagenparameter angegeben sind (z. B. bp foo!bar<int>), dann wird ein Haltepunkt an der spezifischen Implementierung der Vorlagenfunktion gesetzt.

    • Wenn der Ausdruck keine Typimplementierung angegeben hat (z. B bp foo!bar), werden keine Haltepunkte festgelegt. In diesem Fall sollte bm verwendet werden, um Haltepunkte in der Vorlagenfunktion festzulegen.

    • Partielle Vorlagenspezifikationen werden vom Debugger nicht unterstützt und in diesem Fall werden keine Haltepunkte gesetzt.

  • Eine Inlinefunktion: Jeder Inline-Speicherort hat einen Haltepunkt

Beachten Sie, dass mehrere Haltepunkte nicht festgelegt werden, wenn der Symbolausdruck Operatoren oder Offsets enthält, die eine weitere Auswertung durch den Debugger erfordern. Wenn das Symbol foo beispielsweise an mehreren Positionen aufgelöst wird, aber der Ausdruck foo+5 ausgewertet wird, versucht der Debugger nicht, alle Positionen für festzulegende Haltepunkte aufzulösen.

Beispiele für Haltepunktcode

Ausgehend vom folgenden Codeausschnitt:

class BikeCatalog
{
public:
    void GetNumberOfBikes()
    {
        std::cout << "There are 42 bikes." << std::endl;
    }
    int GetNumberOfBikes(int num)
    {
        std::cout << "There are " << num << " bikes." << std::endl;
        return num;
    }
}; 

Das Aufrufen des Befehls bu BikeCatalog::GetNumberOfBikes würde zur Erstellung von zwei Haltepunkten führen, einer für jede Überladung. Das Auflisten der Haltepunkte würde zu folgender Ausgabe führen:

0:000> bl
     2 e Disable Clear  <hierarchical breakpoint>     0001 (0001)  0:**** {BikeCatalog!BikeCatalog::GetNumberOfBikes}
         0 e Disable Clear  00007ff6`c6f52200  [C:\BikeCatalog\BikeCatalog.cpp @ 13]     0001 (0001)  0:**** BikeCatalog!BikeCatalog::GetNumberOfBikes
         1 e Disable Clear  00007ff6`c6f522a0  [C:\BikeCatalog\BikeCatalog.cpp @ 9]     0001 (0001)  0:**** BikeCatalog!BikeCatalog::GetNumberOfBikes

Mehrdeutige Quellzeilen

Das Festlegen eines Haltepunkts in einer Quellzeile sollte zu folgendem Verhalten führen, wenn es sich bei der Quellzeile um Folgendes handelt:

  • Eine compileroptimierte Funktion: Wenn die Zeile aufgrund von Compileroptimierungen an mehreren Positionen aufgeteilt wird, wird an der untersten Stelle innerhalb der Funktion, die der angegebenen Zeile entspricht, ein Haltepunkt gesetzt.
  • Eine Inlinefunktion: Für jede der Aufrufstellen wird ein Haltepunkt gesetzt, es sei denn, die angegebene Zeile wurde im Rahmen der Inline-Erstellung optimiert.
  • An mehreren Positionen aufgelöst: Wenn die oben genannten Bedingungen nicht erfüllt sind, wird für jede Adresse ein Haltepunkt mit den folgenden Bedingungen gesetzt:
    • Wenn eine Reihe von N-Adressen vorhanden ist, die mit der Quellzeile im Ausdruck übereinstimmen, und eine Teilmenge M dieser N-Adressen keine Quellzeilenverschiebung aus der Quellzeile im Ausdruck hat, dann verfügen nur die M-Adressen über Haltepunkte.
    • Wenn in der Gruppe von N-Adressen keine Adressen vorhanden sind, die keine Quellzeilenverschiebung aus der Quellzeile im Ausdruck aufweisen, weisen alle N-Adressen Haltepunkte auf.

Filtern basierend auf dem Symbolindex

Jedes Symbol sollte über einen eindeutigen Symbolindex verfügen. Ausführliche Informationen zur Struktur von Symbolen finden Sie unter SYMBOL_INFO-Struktur.

Der Debugger verwendet den Symbolindex, um sicherzustellen, dass duplizierte Übereinstimmungen im Falle mehrerer Adressen mit Null-Quellzeilenverschiebung gefiltert werden.

Beispiele für Vorlagen und überladene Funktionen

Funktionen von Azure-Ressourcen-Manager-Vorlagen

Das Setzen eines Haltepunkts in der Quellzeile für die Definition einer Vorlagenfunktion führt zu einem Haltepunkt für jede Implementierung der Vorlagenfunktion. Aufgrund der folgenden Vorlagenfunktion in Zeile 19 von BikeCatalog.cpp:

template <class T>
void RegisterBike(T id)
{
    std::cout << "Registered bike " << id << std::endl;
}

Und seiner Verwendungen:

catalog.RegisterBike("gravel bike");
catalog.RegisterBike(1234);

Durch Aufrufen des Befehls bp `BikeCatalog.cpp:19` werden zwei Haltepunkte festgelegt, die in die Implementierungen der Vorlagenfunktion aufgelöst werden, die später in der Datei verwendet werden. Wenn der Benutzer stattdessen einen einzelnen Haltepunkt für die Funktion festlegen wollte, müsste er entweder einen Haltepunkt in der spezifischen Quellzeile der Implementierung der Vorlagenfunktion festlegen oder einen Haltepunkt für das Symbol der Vorlagenfunktion mit den entsprechenden Typinformationen festlegen (z. B. bp BikeCatalog::RegisterBike<int>).

Das Auflisten der Haltepunkte führt zu folgender Ausgabe:

0:000> bl
     2 e Disable Clear  <hierarchical breakpoint>     0001 (0001)  0:**** {BikeCatalog!BikeCatalog::RegisterBike&lt;int&gt;}
         0 e Disable Clear  00007ff7`6b691dd0  [C:\BikeCatalog\BikeCatalog.cpp @ 20]     0001 (0001)  0:**** BikeCatalog!BikeCatalog::RegisterBike<int>
         1 e Disable Clear  00007ff7`6b691e60  [C:\BikeCatalog\BikeCatalog.cpp @ 20]     0001 (0001)  0:**** BikeCatalog!BikeCatalog::RegisterBike<char const *>

Überladene Funktionen

Das Setzen eines Haltepunkts in der Quellzeile für die Definition einer überladenen Funktion führt zu nur einem Haltepunkt in dieser Definition der überladenen Funktion. Wiederverwendung des obigen Codeausschnitts, wobei die erste Zeile in Zeile 5 beginnt:

class BikeCatalog
{
public:
    void GetNumberOfBikes()
    {
        std::cout << "There are 42 bikes." << std::endl;
    }
    int GetNumberOfBikes(int num)
    {
        std::cout << "There are " << num << " bikes." << std::endl;
        return num;
    }
}; 

Wenn Sie den Befehl bp `BikeCatalog.cpp:9` aufrufen, wird ein einzelner Haltepunkt in der Zeile für die void-Implementierung von GetNumberOfBikes gesetzt. Das Auflisten der Haltepunkte führt zu folgender Ausgabe:

0:000> bl
     0 e Disable Clear  00007ff7`6b691ec0  [C:\BikeCatalog\BikeCatalog.cpp @ 9]     0001 (0001)  0:**** BikeCatalog!BikeCatalog::GetNumberOfBikes

Inlinefunktionen

Das Setzen eines Haltepunkts in der Quellzeile für die Aufrufstelle einer integrierten Funktion führt nur zu einem Haltepunkt an dieser bestimmten Aufrufstelle, selbst wenn in derselben Funktion eine andere Aufrufstelle vorhanden ist.

Mehrere hierarchische Haltepunkte

Hierarchische Haltepunkte besitzen jeden Haltepunkt in seiner Gruppe, es sei denn:

Ein Haltepunkt in seinem Satz wird gelöscht.

  • Der hierarchische Haltepunkt wird gelöscht.
  • Ein weiterer hierarchischer Haltepunkt wird erstellt, der einen Haltepunkt in diesem hierarchischen Haltepunktsatz enthält.

Eine andere Möglichkeit, dies zu betrachten, besteht darin, dass Haltepunkte möglicherweise nur einen hierarchischen Haltepunktbesitzer haben und dass der letzte Haltepunktbefehl den Status der Haltepunktliste bestimmt.

Darüber hinaus kann ein hierarchischer Haltepunkt keinen anderen hierarchischen Haltepunkt besitzen.

Zusammenfassen vorhandener Haltepunkte

Wenn ein Haltepunkt A eigenständig vorhanden ist und ein mehrdeutiger Haltepunktausdruck aufgelöst wird, um Haltepunkte A, B zu erstellen, wird A in den neuen Haltepunktsatz mit B aufgenommen.

Zusammenfassen hierarchischer Haltepunktsatz-Überschneidungen

Wenn ein hierarchischer Haltepunkt A die Haltepunkte B, C besitzt und dann ein mehrdeutiger Haltepunktausdruck aufgelöst wird, um Haltepunkte zu erstellen:

  • B, C, D: Haltepunkte B, C tritt der neuen hierarchischen Haltepunktgruppe mit Haltepunkt D bei und der hierarchische Haltepunkt A wird gelöscht.

  • C, D or B, D: Einer der Haltepunkte tritt der neuen hierarchischen Haltepunktgruppe mit Haltepunkt D bei und der hierarchische Haltepunkt A bleibt mit dem einen verbleibenden Haltepunkt bestehen, der der neuen Gruppe nicht beigetreten ist.

Weitere Informationen

Verwenden von Haltepunkten

Haltepunktsyntax

bp, bu, bm (Set Breakpoint)

Nicht aufgelöste Haltepunkte (bu Breakpoints)