Compartir a través de


Resolución de puntos de interrupción ambiguos

En la versión 10.0.25310.1001 y posteriores del motor del depurador, ahora se admite la resolución de puntos de interrupción ambiguos.

Los puntos de interrupción ambiguos permiten al depurador establecer puntos de interrupción en determinados escenarios en los que una expresión de punto de interrupción se resuelve en varias ubicaciones. Por ejemplo, esto puede ocurrir cuando:

  • Hay varias sobrecargas de una función.
  • Hay varios símbolos que coinciden con una expresión de punto de interrupción.
  • El mismo nombre de símbolo se usa para varias ubicaciones.
  • El símbolo se ha insertado.
  • Se establecer un punto de interrupción en una función de plantilla con varias instancias en la ventana de origen.

Cuando se habilita, el depurador establecerá un punto de interrupción en cada coincidencia de símbolos para una expresión de punto de interrupción determinada. El depurador también filtrará las coincidencias de símbolos si se cumplen determinados criterios.

Para obtener información general sobre el uso de puntos de interrupción, consulte Uso de puntos de interrupción.

Habilitación de la resolución de puntos de interrupción ambiguos

De forma predeterminada, los puntos de interrupción ambiguos están deshabilitados. Para habilitarlo en una sesión del depurador, ejecute este comando en la consola de WinDbg:

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

Para confirmar que la configuración de puntos de interrupción ambiguos está activa:

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

Para obtener más información sobre el uso del comando dx, consulte dx (Mostrar la expresión del modelo de objeto del depurador).

Para deshabilitar la característica, establezca el valor anterior en false. Para asegurarse de que la configuración persiste entre sesiones, asegúrese de hacer clic en File -> Settings -> Debugger Settings y, a continuación, marque la casilla marcada como Persist engine settings across debugger sessions.

El uso se aplica a puntos de interrupción únicos

La resolución de expresiones de puntos de interrupción ambiguos solo se aplica a la ejecución del comando de punto de interrupción para establecer un único punto de interrupción en el depurador. En otras palabras, establecer varios puntos de interrupción con el comando bm seguirá funcionando como de costumbre. Al ejecutar el comando con esta característica habilitada, se producirá un nuevo comportamiento de punto de interrupción para puntos de interrupción únicos.

Para obtener información general sobre los comandos de punto de interrupción, consulte bp, bu, bm (Establecer punto de interrupción).

Puntos de interrupción jerárquicos

Los puntos de interrupción jerárquicos representan el resultado de resolver una expresión de punto de interrupción ambiguo en varios puntos de interrupción. Si una expresión da como resultado dos o más coincidencias que se usarán para establecer puntos de interrupción, se crea otro punto de interrupción que controlará el conjunto de puntos de interrupción. Este punto de interrupción de invalidación, el punto de interrupción jerárquico, se puede habilitar, deshabilitar o borrar y mostrar como lo haría un punto de interrupción normal, con la funcionalidad agregada de realizar la misma operación en los puntos de interrupción que posee.

Por ejemplo, si se ejecuta el comando bp foo!bar, lo que da como resultado dos coincidencias con el símbolo bar, se creará un punto de interrupción jerárquico que controla las dos coincidencias. Si la jerarquía está habilitada, deshabilitada o desactivada, también lo estarán los puntos de interrupción coincidentes.

.bpcmds (Mostrar comandos de puntos de interrupción) enumerará el comando de punto de interrupción que se puede ejecutar para establecer cada punto de interrupción. Los puntos de interrupción que pertenecen a un punto de interrupción jerárquico seguirán enumerando un comando bp válido que establecerá un punto de interrupción en su dirección. Los puntos de interrupción jerárquicos también se mostrarán en la salida y mostrarán el comando que se puede usar para volver a crear todo el conjunto de puntos de interrupción en lugar de solo un punto de interrupción.

Símbolos ambiguos

Si se establece un punto de interrupción en un nombre de símbolo, se debe producir el siguiente comportamiento si el símbolo es:

  • Una sobrecarga: cada sobrecarga que coincida con el símbolo debe tener un punto de interrupción.

  • Una función de plantilla:

    • Si la expresión tiene todos los parámetros de plantilla especificados (por ejemplo bp foo!bar<int>), se establecerá un punto de interrupción en la implementación específica de la función de plantilla.

    • Si la expresión no tiene ninguna implementación de tipo especificada (por ejemplo bp foo!bar), no se establecerá ningún punto de interrupción. En este caso, se debe usar bm para establecer puntos de interrupción en la función de plantilla.

    • El depurador no admite especificaciones de plantilla parciales y no se establecerán puntos de interrupción en ese caso.

  • Una función insertada: cada ubicación insertada tiene un punto de interrupción.

Tenga en cuenta que no se establecerán varios puntos de interrupción cuando la expresión de símbolo incluya operadores o desplazamientos que requieran más evaluación por parte del depurador. Por ejemplo, si el símbolo foo se resuelve en varias ubicaciones, pero se evalúa la expresión foo+5, el depurador no intentará resolver todas las ubicaciones para que se establezcan puntos de interrupción.

Ejemplos de código de punto de interrupción

Dado el siguiente fragmento 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;
    }
}; 

Al invocar el comando bu BikeCatalog::GetNumberOfBikes, se crearían dos puntos de interrupción, uno para cada sobrecarga. La enumeración de los puntos de interrupción daría como resultado la siguiente salida:

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

Líneas de origen ambiguas

Si se establece un punto de interrupción en una línea de origen, se debe producir el siguiente comportamiento si la línea de origen es:

  • Una función optimizada para el compilador: si la línea se divide en varias ubicaciones debido a optimizaciones del compilador, se establecerá un punto de interrupción en la ubicación más baja dentro de la función correspondiente a la línea especificada.
  • Una función insertada: se establece un punto de interrupción para cada uno de los sitios de llamada, a menos que la línea especificada se haya optimizado como parte de la inserción.
  • Se resuelve en varias ubicaciones: si no se cumplen las condiciones anteriores, se establecerá un punto de interrupción para cada dirección con las condiciones siguientes:
    • Si hay un conjunto de direcciones N que coinciden con la línea de origen de la expresión y un subconjunto M de estas direcciones N tienen un desplazamiento de línea de origen cero desde la línea de origen de la expresión, solo las direcciones M tendrán puntos de interrupción.
    • Si no hay ninguna dirección en el conjunto de direcciones N que tengan un desplazamiento de línea de origen cero desde la línea de origen de la expresión, todas las direcciones N tendrán puntos de interrupción.

Filtrado basado en el índice de símbolos

Cada símbolo debe tener un índice de símbolo único. Para obtener información detallada sobre la estructura de símbolos, consulte Estructura SYMBOL_INFO.

El depurador usará el índice de símbolos para asegurarse de que las coincidencias duplicadas se filtran en caso de varias direcciones con desplazamiento de línea de origen cero.

Ejemplos de funciones sobrecargadas y de plantilla

Funciones de plantillas

Si se establece un punto de interrupción en la línea de origen para la definición de una función de plantilla, se producirá un punto de interrupción para cada implementación de la función de plantilla. Dada la siguiente función de plantilla en la línea 19 de BikeCatalog.cpp:

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

Y sus usos:

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

Al invocar el comando bp `BikeCatalog.cpp:19` , se establecerán dos puntos de interrupción que se resuelven en las implementaciones de la función de plantilla que se usan más adelante en el archivo. Si en su lugar el usuario quisiera establecer un único punto de interrupción en la función, tendría que establecer un punto de interrupción en la línea de origen específica de la implementación de la función de plantilla o establecer un punto de interrupción en el símbolo de la función de plantilla con la información de tipo adecuada (por ejemplo, bp BikeCatalog::RegisterBike<int>).

Enumerar los puntos de interrupción da como resultado la siguiente salida:

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

Acciones sobrecargadas

Si se establece un punto de interrupción en la línea de origen para la definición de una función sobrecargada, solo se producirá un punto de interrupción en esa definición de la función sobrecargada. Reutilización del fragmento de código anterior, con la primera línea a partir de la línea 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;
    }
}; 

Al invocar el comando bp `BikeCatalog.cpp:9` , se establecerá un único punto de interrupción en la línea de la implementación void de GetNumberOfBikes. Enumerar los puntos de interrupción da como resultado la siguiente salida:

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

funciones insertadas

Si se establece un punto de interrupción en la línea de origen para el sitio de llamada de una función insertada, solo se producirá un punto de interrupción en ese sitio de llamada concreto, incluso si hay otro sitio de llamada presente en la misma función.

Varios puntos de interrupción jerárquicos

Los puntos de interrupción jerárquicos serán propietarios de cada punto de interrupción de su conjunto a menos que:

Se borre un punto de interrupción en su conjunto

  • Se borre el punto de interrupción jerárquico.
  • Se cree otro punto de interrupción jerárquico que incluya un punto de interrupción en el conjunto de este punto de interrupción jerárquico.

Otra manera de pensar en esto es que los puntos de interrupción solo pueden tener un propietario de punto de interrupción jerárquico y que el comando de punto de interrupción más reciente determinará cuál debe ser el estado de la lista de puntos de interrupción.

Además, un punto de interrupción jerárquico no puede poseer otro punto de interrupción jerárquico.

Subsunción de puntos de interrupción preexistentes

Si existe un punto de interrupción A por sí mismo y, a continuación, se resuelve una expresión de punto de interrupción ambigua para crear loa puntos de interrupción A, B, A se incluirá en el nuevo conjunto de puntos de interrupción con B.

Subsunción de intersecciones de conjunto de puntos de interrupción jerárquicos

Si un punto de interrupción jerárquico A posee los puntos de interrupción B, C y, a continuación, se resuelve una expresión de punto de interrupción ambiguo para crear puntos de interrupción:

  • B, C, D: los puntos de interrupción B, C se unirán al nuevo grupo de puntos de interrupción jerárquicos con el punto de interrupción D y el punto de interrupción jerárquico A se eliminará.

  • C, D or B, D: uno de los puntos de interrupción se unirá al nuevo grupo de puntos de interrupción jerárquicos con el punto de interrupción D y el punto de interrupción jerárquico A seguirá existiendo con el otro punto de interrupción que no se unió al nuevo grupo.

Consulte también

Usar puntos de interrupción

Sintaxis de punto de interrupción

bp, bu, bm (Establecer punto de interrupción)

Puntos de interrupción sin resolver (puntos de interrupción bu)