Risoluzione ambigua dei punti di interruzione

Nella versione 10.0.25310.1001 e successive del motore del debugger è ora supportata la risoluzione ambigua dei punti di interruzione.

I punti di interruzione ambigui consentono al debugger di impostare punti di interruzione in determinati scenari in cui un'espressione del punto di interruzione viene risolta in più posizioni. Ad esempio, questo può verificarsi quando:

  • Più overload di una funzione.
  • Esistono più simboli che corrispondono a un'espressione di punto di interruzione.
  • Lo stesso nome di simbolo viene usato per più posizioni.
  • Il simbolo è stato inlinede.
  • Impostazione di un punto di interruzione in una funzione modello con più istanze nella finestra di origine.

Se abilitata, il debugger imposta un punto di interruzione per ogni corrispondenza del simbolo per un'espressione di punto di interruzione specificata. Il debugger filtra anche le corrispondenze dei simboli se vengono soddisfatti determinati criteri.

Per informazioni generali sull'uso dei punti di interruzione, vedere Uso di punti di interruzione.

Abilitazione della risoluzione ambigua dei punti di interruzione

Per impostazione predefinita, i punti di interruzione ambigui sono disabilitati. Per abilitare questa operazione in una sessione del debugger, eseguire questo comando nella console WinDbg:

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

Per verificare che l'impostazione dei punti di interruzione ambigua sia attiva:

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

Per altre informazioni sull'uso del comando dx, vedere dx (Display Debugger Object Model Expression).

Per disabilitare la funzionalità, impostare il valore precedente su false. Per assicurarsi che l'impostazione venga mantenuta tra le sessioni, assicurarsi di fare clic su File -> Settings -> Debugger Settings e quindi selezionare la casella contrassegnata da Persist engine settings across debugger sessions.

L'utilizzo si applica a singoli punti di interruzione

La risoluzione di espressioni di punti di interruzione ambigue si applica solo all'esecuzione del comando del punto di interruzione per impostare un singolo punto di interruzione nel debugger. In altre parole, l'impostazione di più punti di interruzione con il bm comando continuerà a funzionare come di consueto. L'esecuzione del comando con questa funzionalità abilitata comporterà un nuovo comportamento del punto di interruzione per i singoli punti di interruzione.

Per informazioni generali sui comandi del punto di interruzione, vedere bp, bu, bm (Set Breakpoint).

Punti di interruzione gerarchici

I punti di interruzione gerarchici rappresentano il risultato della risoluzione di un'espressione di punti di interruzione ambigua in più punti di interruzione. Se un'espressione restituisce due o più corrispondenze che verranno utilizzate per impostare i punti di interruzione, viene creato un altro punto di interruzione che controllerrà il set di punti di interruzione. Questo punto di interruzione di override, il punto di interruzione gerarchico, può essere abilitato/disabilitato/cancellato ed elencato esattamente come un normale punto di interruzione, con la funzionalità aggiunta di eseguire la stessa operazione sui punti di interruzione di cui è proprietario.

Ad esempio, se il comando bp foo!bar viene eseguito, con due corrispondenze con il simbolo bar, verrà creato un punto di interruzione gerarchico che controlla le due corrispondenze. Se la gerarchia è abilitata/disabilitata/deselezionata, anche i punti di interruzione corrispondenti saranno.

I comandi con estensione bpcmds(Visualizza i comandi del punto di interruzione) elencano il comando del punto di interruzione che può essere eseguito per impostare ogni punto di interruzione. I punti di interruzione di proprietà di un punto di interruzione gerarchico elencano comunque un comando bp valido che imposta un punto di interruzione sul relativo indirizzo. I punti di interruzione gerarchici verranno elencati anche nell'output e visualizzeranno il comando che può essere usato per ricreare l'intero set di punti di interruzione anziché un solo punto di interruzione.

Simboli ambigui

L'impostazione di un punto di interruzione su un nome di simbolo dovrebbe comportare il comportamento seguente se il simbolo è:

  • Overload: ogni overload che corrisponde al simbolo deve avere un punto di interruzione.

  • Funzione modello:

    • Se l'espressione ha tutti i parametri del modello specificati (ad esempio bp foo!bar<int>), verrà impostato un punto di interruzione sull'implementazione specifica della funzione modello.

    • Se l'espressione non ha un'implementazione del tipo specificata ,ad esempio bp foo!bar, non verrà impostato alcun punto di interruzione. In questo caso, bm deve essere usato per impostare i punti di interruzione nella funzione modello.

    • Le specifiche dei modelli parziali non sono supportate dal debugger e in questo caso non verranno impostati punti di interruzione.

  • Funzione inlined: ogni posizione inlined ha un punto di interruzione

Si noti che non verranno impostati più punti di interruzione quando l'espressione simbolo include operatori o offset che richiedono una valutazione maggiore da parte del debugger. Ad esempio, se il simbolo foo viene risolto in più posizioni, ma l'espressione foo+5 viene valutata, il debugger non tenterà di risolvere tutti i percorsi per i punti di interruzione da impostare.

Esempi di codice del punto di interruzione

Dato il frammento di codice seguente:

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;
    }
}; 

Il richiamo del comando bu BikeCatalog::GetNumberOfBikes comporta la creazione di due punti di interruzione, uno per ogni overload. L'elenco dei punti di interruzione genera l'output seguente:

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

Righe di origine ambigue

L'impostazione di un punto di interruzione su una riga di origine dovrebbe comportare il comportamento seguente se la riga di origine è:

  • Funzione ottimizzata per il compilatore: se la riga viene suddivisa in più posizioni a causa delle ottimizzazioni del compilatore, verrà impostato un punto di interruzione nella posizione più bassa all'interno della funzione corrispondente alla riga specificata.
  • Funzione inlined: un punto di interruzione viene impostato per ognuno dei siti di chiamata, a meno che la riga specificata non sia stata ottimizzata come parte dell'inlining.
  • Risolto in più posizioni: se le condizioni precedenti non vengono soddisfatte, verrà impostato un punto di interruzione per ogni indirizzo con le condizioni seguenti:
    • Se è presente un set di indirizzi N che corrispondono alla riga di origine nell'espressione e un subset M di questi indirizzi N ha uno spostamento di riga di origine zero dalla riga di origine nell'espressione, solo gli indirizzi M avranno punti di interruzione.
    • Se non sono presenti indirizzi nel set di indirizzi N che hanno uno spostamento di riga di origine zero dalla riga di origine nell'espressione, tutti gli N indirizzi avranno punti di interruzione.

Applicazione di filtri in base all'indice dei simboli

Ogni simbolo deve avere un indice di simboli univoco. Per informazioni dettagliate sulla struttura dei simboli, vedere SYMBOL_INFO struttura.

Il debugger userà l'indice dei simboli per assicurarsi che le corrispondenze duplicate vengano filtrate in caso di più indirizzi con spostamento di riga di origine zero.

Esempi di modelli e funzioni di overload

Funzioni di modello

L'impostazione di un punto di interruzione nella riga di origine per la definizione di una funzione modello comporterà un punto di interruzione per ogni implementazione della funzione modello. Data la funzione modello seguente alla riga 19 di BikeCatalog.cpp:

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

E i relativi utilizzi:

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

Il richiamo del comando bp `BikeCatalog.cpp:19` imposta due punti di interruzione che vengono risolti nelle implementazioni della funzione modello usate più avanti nel file. Se invece l'utente desidera impostare un singolo punto di interruzione sulla funzione, dovrà impostare un punto di interruzione sulla riga di origine specifica dell'implementazione della funzione modello o impostare un punto di interruzione sul simbolo della funzione modello con le informazioni sul tipo appropriate , ad esempio bp BikeCatalog::RegisterBike<int>.

Elencare i punti di interruzione nell'output seguente:

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 *>

Funzioni di overload

L'impostazione di un punto di interruzione nella riga di origine per la definizione di una funzione di overload comporterà un solo punto di interruzione su tale definizione della funzione di overload. Riutilizzo del frammento di codice precedente, con la prima riga che inizia alla riga 5:

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;
    }
}; 

Il richiamo del comando bp `BikeCatalog.cpp:9` imposta un singolo punto di interruzione nella riga per l'implementazione void di GetNumberOfBikes. Elencare i punti di interruzione nell'output seguente:

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

funzioni inlined

L'impostazione di un punto di interruzione nella riga di origine per il sito di chiamata di una funzione inlined genererà un solo punto di interruzione in quel particolare sito di chiamata, anche se nella stessa funzione è presente un altro sito di chiamata.

Più punti di interruzione gerarchici

I punti di interruzione gerarchici saranno proprietari di ogni punto di interruzione nel set, a meno che:

Un punto di interruzione nel set viene cancellato

  • Il punto di interruzione gerarchico viene cancellato.
  • Viene creato un altro punto di interruzione gerarchico che include un punto di interruzione nel set di punti di interruzione gerarchici.

Un altro modo per considerare questa situazione è che i punti di interruzione possono avere un solo proprietario del punto di interruzione gerarchico e che il comando del punto di interruzione più recente determinerà lo stato dell'elenco dei punti di interruzione.

Inoltre, un punto di interruzione gerarchico non può possedere un altro punto di interruzione gerarchico.

Ripresa di punti di interruzione preesistenti

Se un punto di interruzione A esiste da solo e quindi viene risolta un'espressione di punto di interruzione ambigua per creare punti di interruzione A, B, Averrà incluso nel nuovo punto di interruzione impostato con B.

Subsuming hierarchical breakpoint set intersezioni

Se un punto di interruzione gerarchico A possiede punti di interruzione B, C e quindi viene risolta un'espressione di punto di interruzione ambigua per creare punti di interruzione:

  • B, C, D: Punti di interruzione B, C unisce il nuovo gruppo di punti di interruzione gerarchico con il punto di interruzione D e il punto di interruzione gerarchico A verrà cancellato.

  • C, D o B, D: uno dei punti di interruzione unisce il nuovo gruppo di punti di interruzione gerarchico con il punto di interruzione D e il punto di interruzione gerarchico A continuerà a esistere con quello rimanente che non è stato aggiunto al nuovo gruppo.

Vedi anche

Uso di punti di interruzione

Sintassi del punto di interruzione

bp, bu, bm (Imposta punto di interruzione)

Punti di interruzione non risolti (punti di interruzione bu)