Establecer punto de interrupción en código C o C ++ mediante programación para gdb en Linux

105

¿Cómo puedo establecer un punto de interrupción en el código C o C ++ programáticamente que funcionará para gdb en Linux?

Es decir:

int main(int argc, char** argv)
{
    /* set breakpoint here! */
    int a = 3;
    a++;  /*  In gdb> print a;  expect result to be 3 */
    return 0;
}
J. Polfer
fuente
8
Una nota al margen (lo siento por ser quisquilloso), pero si está preocupado por la portabilidad, probablemente también esté preocupado por la corrección, por lo tanto, en int mainlugar de void main.
Stuart Golodetz
@Stuart - Fijo. Debería haberlo hecho hace un tiempo.
J. Polfer
4
@ J.Polfer: Sin return 0embargo, no es necesario, ¡y es solo ruido!
Lightness Races in Orbit

Respuestas:

107

Una forma es señalar una interrupción:

#include <csignal>

// Generate an interrupt
std::raise(SIGINT);

C ª:

#include <signal.h>
raise(SIGINT);

ACTUALIZACIÓN : MSDN afirma que Windows realmente no es compatible SIGINT, por lo que si la portabilidad es un problema, probablemente sea mejor que lo use SIGABRT.

Håvard S
fuente
Sí, esto debería funcionar en todos los sistemas operativos / compiladores / depuradores.
Håvard S
1
No conozco otros depuradores, pero gdb es bastante flexible en cuanto al manejo de señales .
Cascabel
4
Encontramos SIGTRAP mejor en algunos Unices
JBRWilkinson
1
en Windows, MSVC puede utilizar __debug_break, DebugBreak o _asm {int 3}.
Fernando Gonzalez Sanchez
2
@FernandoGonzalezSanchez: en realidad, el nombre de la función es __debugbreak()y NO __debug_break() , como puede ver aquí
Morix Dev
27

En un proyecto en el que trabajo, hacemos esto:

raise(SIGABRT);  /* To continue from here in GDB: "signal 0". */

(En nuestro caso, queríamos bloquear con fuerza si esto sucedía fuera del depurador, generando un informe de bloqueo si fuera posible. Esa es una de las razones por las que usamos SIGABRT. Hacer esto de manera portátil en Windows, Mac y Linux requirió varios intentos. Terminamos con algunos #ifdefs, comentado amablemente aquí: http://hg.mozilla.org/mozilla-central/file/98fa9c0cff7a/js/src/jsutil.cpp#l66 .)

Jason Orendorff
fuente
2
Como de costumbre, Windows no se parece a los demás :)
mathk
¿Es posible emitir "señal 0" para continuar programando el programa en un estado de pausa? Sería bueno poder usar 'n' o 's' desde este punto, sin que se emita una 'c'.
Jason Doucette
2
@JasonDoucette Si realmente solo desea que el programa se pause, es posible que desee agregar una breakpoint()función en su programa (puede estar vacía o simplemente contener una declaración de impresión) y agregar break breakpointa su ~/.gdbinit.
Jason Orendorff
26

Al mirar aquí , encontré la siguiente forma:

void main(int argc, char** argv)
{
    asm("int $3");
    int a = 3;
    a++;  //  In gdb> print a;  expect result to be 3
}

Esto me parece un poco hackeo. Y creo que esto solo funciona en arquitectura x86.

J. Polfer
fuente
3
Y solo con compiladores que admitan la sintaxis de ensamblado de AT&T. En particular, el compilador de Microsoft ( cl.exe) no admite esta sintaxis, pero usa una sintaxis diferente.
Håvard S
la pregunta era sobre linux, así que supongo que podemos asumir que la sintaxis de gcc funcionará para x86.
js.
Por cierto, probé lo anterior en mi máquina x86 y funcionó. Tenía curiosidad por saber si había una mejor manera de hacerlo. Parece que lo hay.
J. Polfer
2
Estoy usando mingw en Windows, por lo que las otras sugerencias no pueden ayudarme. Elevar la señal SIGINT simplemente termina la aplicación, SIGTRAP no está definido en los encabezados mingw ... El uso de la instrucción int en realidad envía SIGTRAP y gdb se rompe muy bien en la línea apropiada.
Machta
En Linux, int 3genera un SIGTRAP.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
12

__asm__("int $3"); Deberia trabajar:

int main(int argc, char** argv)
{
    /* set breakpoint here! */
    int a = 3;
    __asm__("int $3");
    a++;  /*  In gdb> print a;  expect result to be 3 */
    return 0;
}
hek2mgl
fuente
1
Me gusta #defineesto, para no tener que recordar la sintaxis. Lo tengo esparcido por todo mi código, a veces en lugar de assert(), ya que al detener el depurador, permítame examinar todas las variables y la pila. Y, por supuesto, como afirmar, no tengo que eliminarlo para el código de producción
Mawg dice restablecer a Monica el
Es interesante que esto tenga 10 votos a favor cuando las restricciones de preguntas de "Linux" y "GDB" brindan muchas opciones además de recurrir al ensamblaje, que siempre debería ser un último recurso por el bien de la portabilidad, al menos. Consulte algunas de las otras respuestas.
Benjamin Crawford Ctrl-Alt-Tut
5

Es decepcionante ver tantas respuestas que no utilizan la señal dedicada para los puntos de interrupción del software SIGTRAP:

#include <signal.h>

raise(SIGTRAP); // At the location of the BP.
Benjamin Crawford Ctrl-Alt-Tut
fuente
1

En OS X puedes simplemente llamar std::abort()(podría ser lo mismo en Linux)

dacap
fuente
¿Qué biblioteca?
Alex
Esto es parte de la biblioteca estándar de C ++ y es multiplataforma donde existen compiladores compatibles con C ++ 11. Sin embargo, esto genera SIGABRT, que no es realmente una señal apropiada para generar en este caso.
Benjamin Crawford Ctrl-Alt-Tut