2010-08-12 21 views
16

An earlier question explicó que en x86 el tamaño de los objetos que se ven está limitado por los registros de depuración. Como era de esperar, puedo "mirar" una variable doble. Pero no puedo ver una doble DataMember, por ejemplo,Establecer el punto de observación del hardware GDB/cómo configurar el punto de observación del software

watch pObject->dPrice 

produce

Hardware watchpoint 1: pObject->dPrice 

Pero cuando intenta continuar la ejecución, se dice

No se pudo insertar los puntos de interrupción de hardware: Es posible que haya solicitado demasiados puntos de interrupción/puntos de observación de hardware.

aunque este es el solo punto de interrupción/punto de observación.

Tengo curiosidad de por qué esto es así, pero lo más importante es que hay una forma de evitarlo? De acuerdo con la documentación de GDB, puede usar puntos de observación de software si no puede usar hardware. En este caso, no intenta usar un punto de observación de software. ¿Hay alguna manera de obligarlo a hacerlo?

+0

¿Puede imprimir la dirección de esa variable miembro? Mi sospecha sería que está optimizado en un registro. Si no es así, ¿está alineado correctamente? –

Respuesta

15

sí, se puede:

conjunto can-uso-HW-puntos de observación 0

De 5.1.2 Setting Watchpoints:

Puede forzar BGF utilizar sólo puntos de observación de software con el establecer el comando can-use-hw-watchpoints 0. Con esta variable establecida en cero, GDB nunca intentará usar puntos de observación de hardware, incluso si el sistema subyacente los admite. (Tenga en cuenta que los puntos de observación asistidas por hardware que se establecieron antes de se-uso-HW-puntos de observación a cero aún utilizan el mecanismo de hardware de ver los valores de expresión.)

set can-use-hw-watchpoints

        Establecer si o no usar puntos de observación de hardware.

show can-use-hw-watchpoints

        muestran el modo actual de utilizar puntos de observación de hardware.

+0

Gracias! Estaba leyendo esa sección, pero obviamente no leí con cuidado. –

+1

Funciona, pero es un poco más lento que el hardware. En mi caso, aproximadamente 1/5000 de la velocidad. – wallyk

7

No estoy 100% seguro, pero tengo entendido que cuando mira pObject->dPrice, GDB intenta ver cualquier cosa que pueda cambiar el valor observado.

Utilizando los puntos de observación del software, después de cada paso, GDB comprueba si la expresión ha cambiado. Usando puntos de observación de hardware, GDB tiene que establecer un punto de observación para dprice, como espera, pero también para pObject.

Ahora, etiquetó la pregunta 'x86'. En x86 puede establecer puntos de interrupción para hasta cuatro bytes. Un doble es ocho bytes. Si desea ver un doble, supongo que GDB necesitaría dos puntos de observación de hardware. También necesita un punto de observación adicional para pObject.Supongo que GDB intenta ver todo de pObject, lo que vuelve al problema en la pregunta que ha vinculado en la pregunta.

Cuando quiero hacer algo similar, si estoy seguro de que el puntero pObject no va a cambiar, que suele hacer:

p &pObject->dprice 

Digamos BGF dice que la dirección es (double *) 0xabcdef10, ahora sí:

watch (double *) *0xabcdef10 

y solo veo lo que quiero.

Nota: No tengo GDB abierto delante de mí, por lo que puedo tener la sintaxis exacta para el comando watch incorrecta (con respecto a la ubicación del *), así que échale un vistazo primero.

+2

Sería bueno si gdb ofreciera un atajo para "ver solo el objetivo final" –

+3

@CraigRinger: [Sí.] (Http://stackoverflow.com/questions/25938830/gdb-how-to-force-a -watchpoint-to-not-be-deleted-after-a-function-returned) 'watch -location pObject-> dprice' – Alcaro

+0

@Alcaro: 1. ¿esto es compatible con cualquier versión de gdb? 2. esta es una buena respuesta que debería ser en una respuesta independiente, y no como el comentario de mi respuesta. –

2

Respuesta corta: Use watch -location pObject->dPrice, o la forma abreviada watch -l.

Respuesta larga: Quoting the GDB manual:

Observación de expresiones complejas que hacen referencia a muchas variables también pueden agotar los recursos disponibles para los puntos de observación asistidas por hardware. Eso es porque GDB necesita ver cada variable en la expresión con recursos asignados por separado.

GDB, literalmente, mira la expresión en sí, no importa la dirección a la que apunta. En este caso, significa que el punto de interrupción se activará si se cambia pObject para apuntar a un nuevo dPrice; no solo hay un punto de observación para pObject->dPrice, sino también uno para pObject. Esto puede ser más de lo que está disponible.

Un ejemplo más amplia:

// Set a watchpoint on '*p' before running 
#include <stdio.h> 

int a = 0; 
int b = 0; 
int c = 0; 
int* p = &a; 

int main() 
{ 
    puts("Hi"); // Dummy lines to make the results clearer, watchpoints stop at the line after the change 
    *p = 1; // Breaks: *p was changed from 0 to 1 
    puts("Hi"); 
    a = 2; // Breaks: a is *p, which changed from 1 to 2 
    puts("Hi"); 
    p = &b; // Breaks: p is now b, changing *p from 2 to 0 
    puts("Hi"); 
    p = &c; // Doesn't break: while p changed, *p is still 0 
    puts("Hi"); 
    p = NULL; // Breaks: *p is now unreadable 
    puts("Hi"); 
    return 0; 
} 

En teoría, esto es una característica útil; Puedes ver una expresión compleja, rompiendo tan pronto como sea falsa, algo así como una afirmación constantemente probada. Por ejemplo, puede watch a==b en el programa anterior.

En la práctica, es inesperado, a menudo desencadena este problema, y ​​generalmente no es lo que desea.

Para ver solo la dirección de destino, use watch -location pObject->dPrice. (Esto está disponible a partir de GDB 7.3, lanzado en julio de 2011; si está utilizando algo anterior, use print &pObject->dPrice y watch *(double*)0x12345678, o la dirección que imprima)

+0

Publicación cruzada de esta respuesta a [esta pregunta] (http://stackoverflow.com/questions/3206332/gdb-stops-with-too-many-watchpoints-when-there-is-only-one), responde tanto . – Alcaro

Cuestiones relacionadas