Share via


Resolução ambígua do ponto de interrupção

Na versão 10.0.25310.1001 e posterior do mecanismo de depurador, agora há suporte para a resolução ambígua do ponto de interrupção.

Pontos de interrupção ambíguos permitem que o depurador defina pontos de interrupção em determinados cenários em que uma expressão de ponto de interrupção é resolvida para vários locais. Por exemplo, isso pode acontecer quando:

  • Várias sobrecargas de uma função.
  • Há vários símbolos que correspondem a uma expressão de ponto de interrupção.
  • O mesmo nome de símbolo é usado para vários locais.
  • O símbolo foi embutido.
  • Definindo um ponto de interrupção em uma função de modelo com várias instanciações na janela de origem.

Quando habilitado, o depurador definirá um ponto de interrupção em cada correspondência de símbolo para uma determinada expressão de ponto de interrupção. O depurador também filtrará correspondências de símbolo se determinados critérios forem atendidos.

Para obter informações gerais sobre como usar pontos de interrupção, consulte Usando pontos de interrupção.

Habilitar a resolução ambígua do ponto de interrupção

Por padrão, pontos de interrupção ambíguos são desabilitados. Para habilitar isso em uma sessão de depurador, execute este comando no console do WinDbg:

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

Para confirmar se a configuração de pontos de interrupção ambíguos está ativa:

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

Para obter mais informações sobre como usar o comando dx, consulte dx (Exibir expressão de modelo de objeto do depurador).

Para desabilitar o recurso, defina o valor acima como false. Para garantir que a configuração persista entre as sessões, clique em e, em File -> Settings -> Debugger Settings seguida, marcar a caixa marcada como Persist engine settings across debugger sessions.

O uso se aplica a pontos de interrupção únicos

Resolver expressões de ponto de interrupção ambíguas só se aplica à execução do comando de ponto de interrupção para definir um único ponto de interrupção no depurador. Em outras palavras, definir vários pontos de interrupção com o bm comando continuará funcionando normalmente. Executar o comando com esse recurso habilitado resultará em um novo comportamento de ponto de interrupção para pontos de interrupção únicos.

Para obter informações gerais sobre os comandos de ponto de interrupção, consulte bp, bu, bm (Definir ponto de interrupção).

Pontos de interrupção hierárquicos

Os pontos de interrupção hierárquicos representam o resultado da resolução de uma expressão de ponto de interrupção ambígua para vários pontos de interrupção. Se uma expressão resultar em duas ou mais correspondências que serão usadas para definir pontos de interrupção, outro ponto de interrupção será criado que controlará o conjunto de pontos de interrupção. Esse ponto de interrupção de substituição, o ponto de interrupção hierárquico, pode ser habilitado/desabilitado/desmarcado e listado exatamente como um ponto de interrupção normal faria, com a funcionalidade adicional de executar a mesma operação nos pontos de interrupção que possui.

Por exemplo, se o comando bp foo!bar for executado, resultando em duas correspondências com o símbolo bar, será criado um ponto de interrupção hierárquico que controla as duas correspondências. Se o hierárquico estiver habilitado/desabilitado/limpo, também serão os pontos de interrupção correspondentes.

O .bpcmds(Comandos de Ponto de Interrupção de Exibição) listará o comando de ponto de interrupção que pode ser executado para definir cada ponto de interrupção. Os pontos de interrupção pertencentes a um ponto de interrupção hierárquico ainda listarão um comando bp válido que definirá um ponto de interrupção em seu endereço. Os pontos de interrupção hierárquicos também serão listados na saída e exibirão o comando que pode ser usado para recriar todo o conjunto de pontos de interrupção em vez de apenas um único ponto de interrupção.

Símbolos ambíguos

Definir um ponto de interrupção em um nome de símbolo deve resultar no seguinte comportamento se o símbolo for:

  • Uma sobrecarga: cada sobrecarga que corresponde ao símbolo deve ter um ponto de interrupção.

  • Uma função de modelo:

    • Se a expressão tiver todos os parâmetros de modelo especificados (por exemplo bp foo!bar<int>), um ponto de interrupção será definido na implementação específica da função de modelo.

    • Se a expressão não tiver nenhuma implementação de tipo especificada (por exemplo bp foo!bar), nenhum ponto de interrupção será definido. Nesse caso, bm deve ser usado para definir pontos de interrupção na função de modelo.

    • Não há suporte para especificações parciais de modelo pelo depurador e nenhum ponto de interrupção será definido nesse caso.

  • Uma função embutida: cada local embutido tem um ponto de interrupção

Observe que vários pontos de interrupção não serão definidos quando a expressão de símbolo incluir operadores ou deslocamentos que exigem mais avaliação pelo depurador. Por exemplo, se o símbolo foo for resolvido para vários locais, mas a expressão for avaliada, o depurador não tentará resolve todos os locais para que os pontos de interrupção foo+5 sejam definidos.

Exemplos de código de ponto de interrupção

Dado o seguinte snippet de código:

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

Invocar o comando bu BikeCatalog::GetNumberOfBikes resultaria na criação de dois pontos de interrupção, um para cada sobrecarga. Listar os pontos de interrupção resultaria na seguinte saída:

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

Linhas de origem ambíguas

Definir um ponto de interrupção em uma linha de origem deve resultar no seguinte comportamento se a linha de origem for:

  • Uma função otimizada para compilador: se a linha for dividida em vários locais devido a otimizações do compilador, um ponto de interrupção será definido no local mais baixo dentro da função correspondente à linha especificada.
  • Uma função embutida: um ponto de interrupção é definido para cada um dos sites de chamada, a menos que a linha especificada tenha sido otimizada como parte do inlining.
  • Resolvido para vários locais: se as condições acima não forem atendidas, um ponto de interrupção será definido para cada endereço com as seguintes condições:
    • Se houver um conjunto de N endereços que correspondam à linha de origem na expressão e um subconjunto M desses endereços N tiver nenhum deslocamento de linha de origem da linha de origem na expressão, somente os endereços M terão pontos de interrupção.
    • Se não houver endereços no conjunto de N endereços que não tenham nenhum deslocamento de linha de origem da linha de origem na expressão, todos os endereços N terão pontos de interrupção.

Filtragem com base no índice de símbolo

Cada símbolo deve ter um índice de símbolo exclusivo. Para obter informações detalhadas sobre a estrutura dos símbolos, consulte SYMBOL_INFO estrutura.

O depurador usará o índice de símbolo para garantir que as correspondências duplicadas sejam filtradas no caso de vários endereços com deslocamento de linha de origem zero.

Exemplos de funções de modelo e sobrecarregadas

Funções de modelo

Definir um ponto de interrupção na linha de origem para a definição de uma função de modelo resultará em um ponto de interrupção para cada implementação da função de modelo. Dada a seguinte função de modelo na linha 19 de BikeCatalog.cpp:

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

E seus usos:

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

Invocar o comando bp `BikeCatalog.cpp:19` definirá dois pontos de interrupção que resolve para as implementações da função de modelo que são usadas posteriormente no arquivo. Se, em vez disso, o usuário quisesse definir um único ponto de interrupção na função, ele teria que definir um ponto de interrupção na linha de origem específica da implementação da função de modelo ou definir um ponto de interrupção no símbolo da função de modelo com as informações de tipo apropriadas (por exemplo, bp BikeCatalog::RegisterBike<int>).

Listar os pontos de interrupção resulta na seguinte saída:

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

Funções sobrecarregadas

Definir um ponto de interrupção na linha de origem para a definição de uma função sobrecarregada resultará em apenas um ponto de interrupção nessa definição da função sobrecarregada. Reutilizando o snippet de código acima, com a primeira linha começando na linha 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;
    }
}; 

Invocar o comando bp `BikeCatalog.cpp:9` definirá um único ponto de interrupção na linha para a void implementação de GetNumberOfBikes. Listar os pontos de interrupção resulta na seguinte saída:

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

Funções embutidas

Definir um ponto de interrupção na linha de origem para o site de chamada de uma função embutida resultará em apenas um ponto de interrupção nesse site de chamada específico, mesmo que haja outro site de chamada presente na mesma função.

Vários pontos de interrupção hierárquicos

Os pontos de interrupção hierárquicos terão todos os pontos de interrupção em seu conjunto, a menos que:

Um ponto de interrupção em seu conjunto é limpo

  • O ponto de interrupção hierárquico está limpo.
  • Outro ponto de interrupção hierárquico é criado que inclui um ponto de interrupção no conjunto desse ponto de interrupção hierárquico.

Outra maneira de pensar sobre isso é que os pontos de interrupção podem ter apenas um proprietário de ponto de interrupção hierárquico e que o comando de ponto de interrupção mais recente determinará qual deve ser o estado da lista de pontos de interrupção.

Além disso, um ponto de interrupção hierárquico não pode ter outro ponto de interrupção hierárquico.

Subsumir pontos de interrupção pré-existentes

Se um ponto de interrupção A existir por conta própria e, em seguida, uma expressão de ponto de interrupção ambígua for resolvida para criar pontos de interrupção A, B, A será incluída no novo conjunto de pontos de interrupção com B.

Subsumir interseções de conjunto de pontos de interrupção hierárquicos

Se um ponto de interrupção hierárquico A possuir pontos de interrupção B, C e, em seguida, uma expressão de ponto de interrupção ambígua será resolvida para criar pontos de interrupção:

  • B, C, D: pontos de interrupção B, C unirão o novo grupo de pontos de interrupção hierárquicos com o ponto de interrupção D e o ponto de interrupção hierárquico A será limpo.

  • C, D ou B, D: um dos pontos de interrupção unirá o novo grupo de pontos de interrupção hierárquicos com o ponto de interrupção D e o ponto de interrupção hierárquico A continuará a existir com o ponto de interrupção restante que não se juntou ao novo grupo.

Confira também

Usando pontos de interrupção

Sintaxe de ponto de interrupção

bp, bu, bm (Definir ponto de interrupção)

Pontos de interrupção não resolvidos (bu Breakpoints)