c++ linux gdb x86

c++ - gdb problem setting hardware watchpoint/cómo configurar el punto de mira del software



linux x86 (3)

Una pregunta anterior explicaba que en x86 el tamaño de los objetos que se ven está limitado por los registros de depuración. aquí. Como era de esperar, puedo "mirar" una variable doble. Pero no puedo ver un doble datamember, por ejemplo

watch pObject->dPrice

produce

Hardware watchpoint 1: pObject->dPrice

Pero cuando tratas de continuar la ejecución, dice

Could not insert hardware breakpoints: You may have requested too many hardware breakpoints/watchpoints.

a pesar de que este es el único punto de inflexió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 los documentos 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?


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

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

Ahora, etiquetó la pregunta ''x86''. En x86 puede establecer puntos de interrupción para hasta 4 bytes. Un doble es 8 bytes. Si quieres ver un doble, supongo que gdb necesitaría dos puntos de observación de hardware. También necesita un punto de pObject adicional para pObject . Supongo que gdb intenta ver todo el pObject , que se remonta al problema en la pregunta que enlazó en la pregunta.

Cuando quiero hacer algo similar, si estoy seguro de que el objeto del puntero no cambiará, generalmente lo hago:

p &pObject->dprice

Digamos que gdb dice que la dirección es (double *) 0xabcdef10 , ahora lo hago:

watch (double *) *0xabcdef10

y mira solo lo que quiero.

Nota: No tengo gdb abierto frente a mí, así que puedo tener la sintaxis exacta para el comando de watch incorrecta (con respecto a la ubicación del * ), así que compruébalo primero.


Sí tu puedes:

establecer can-use-hw-watchpoints 0

Desde 5.1.2 Establecer puntos de observación :

Puede obligar a gdb a usar solo puntos de observación de software con el comando set 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 asistidos por hardware que se establecieron antes de establecer can-use-hw-watchpoints en cero seguirán utilizando el mecanismo de hardware de observación de valores de expresión).

set can-use-hw-watchpoints

Establezca si usar o no los puntos de observación de hardware.

show can-use-hw-watchpoints

Muestra el modo actual de usar puntos de observación de hardware.


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

Respuesta larga: Citando el manual de GDB :

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

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

Un ejemplo más completo:

//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, esta 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 más antiguo, use print &pObject->dPrice y watch *(double*)0x12345678 , o la dirección que imprima).