Imposta il punto di interruzione nel codice C o C ++ a livello di codice per gdb su Linux


105

Come posso impostare un punto di interruzione nel codice C o C ++ programmaticamente che funzionerà per gdb su Linux?

Vale a dire:

int main(int argc, char** argv)
{
    /* set breakpoint here! */
    int a = 3;
    a++;  /*  In gdb> print a;  expect result to be 3 */
    return 0;
}

8
Molto una nota a margine (scusate il pelo nell'uovo), ma se siete preoccupati per la portabilità, probabilmente siete anche preoccupati per la correttezza, quindi int mainpiuttosto che void main.
Stuart Golodetz

@Stuart - Risolto. Avrei dovuto farlo tempo fa.
J. Polfer

4
@ J.Polfer: Il return 0non è necessario, però, ed è solo rumore!
Gare di leggerezza in orbita

Risposte:


107

Un modo è segnalare un'interruzione:

#include <csignal>

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

In C:

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

AGGIORNAMENTO : MSDN afferma che Windows non supporta realmente SIGINT, quindi se la portabilità è un problema, probabilmente faresti meglio a usarlo SIGABRT.


Sì, dovrebbe funzionare su tutti i sistemi operativi / compilatori / debugger.
Håvard S

1
Non conosco altri debugger, ma gdb è abbastanza flessibile sulla gestione del segnale .
Cascabel

4
Abbiamo trovato SIGTRAP migliore su alcuni Unix
JBRWilkinson

1
in Windows, MSVC puoi usare __debug_break, DebugBreak o _asm {int 3}.
Fernando Gonzalez Sanchez,

2
@FernandoGonzalezSanchez: in realtà il nome della funzione è __debugbreak()e NON __debug_break() , come puoi vedere qui
Morix Dev

27

In un progetto su cui lavoro, facciamo questo:

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

(Nel nostro caso volevamo un arresto anomalo se questo accadeva al di fuori del debugger, generando un rapporto di arresto anomalo se possibile. Questo è uno dei motivi per cui abbiamo utilizzato SIGABRT. Per farlo in modo portabile su Windows, Mac e Linux sono stati necessari diversi tentativi. Abbiamo finito con alcuni #ifdefs, utilmente commentato qui: http://hg.mozilla.org/mozilla-central/file/98fa9c0cff7a/js/src/jsutil.cpp#l66 .)


2
Come al solito Windows non assomiglia alle altre :)
mathk

È possibile emettere "segnale 0" per continuare il programma in uno stato di pausa? Sarebbe bello poter usare "n" o "s" da questo punto, senza che venga emessa una "c".
Jason Doucette

2
@JasonDoucette Se vuoi solo mettere in pausa il programma, potresti voler aggiungere una breakpoint()funzione nel tuo programma (può essere vuoto o contenere solo un'istruzione print) e aggiungerla break breakpointal tuo file ~/.gdbinit.
Jason Orendorff

26

Guardando qui , ho trovato il modo seguente:

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

Questo mi sembra un po 'hacker. E penso che funzioni solo su architettura x86.


3
E solo con i compilatori che supportano la sintassi dell'assembly AT&T. In particolare, il compilatore di Microsoft ( cl.exe) non supporta questa sintassi, ma utilizza una sintassi diversa.
Håvard S

la domanda riguardava linux, quindi immagino che possiamo presumere che la sintassi di gcc funzionerà per x86.
js.

BTW - Ho provato quanto sopra sulla mia macchina x86 e ha funzionato. Ero curioso di sapere se ci fosse un modo migliore per farlo. Sembra che ci sia.
J. Polfer

2
Sto usando mingw su Windows quindi gli altri suggerimenti non possono aiutarmi. L'aumento del segnale SIGINT termina semplicemente l'applicazione, SIGTRAP non è definito nelle intestazioni mingw ... L'uso dell'istruzione int effettivamente invia SIGTRAP e gdb interrompe bene la riga appropriata.
Machta

In Linux, int 3solleva un SIGTRAP.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

12

__asm__("int $3"); dovrebbe funzionare:

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

1
Mi piace #definequesto, così non devo ricordarmi la sintassi. L'ho cosparso in tutto il mio codice, a volte al posto di assert(), poiché l'arresto del debiugger mi consente di esaminare tutte le variabili e lo stack. E, naturalmente, come asserire, non devo rimuoverlo per il codice di produzione
Mawg dice reinstate Monica

È interessante notare che questo ha 10 voti positivi quando i vincoli della domanda di "Linux" e "GDB" offrono molte opzioni al di fuori del ricorso all'assembly, che dovrebbe sempre essere l'ultima risorsa per motivi di portabilità se non altro. Si prega di vedere alcune delle altre risposte.
Benjamin Crawford Ctrl-Alt-Tut

5

Deludente vedere così tante risposte non si utilizza il segnale dedicato per i punti di interruzione di software, SIGTRAP:

#include <signal.h>

raise(SIGTRAP); // At the location of the BP.

1

Su OS X puoi semplicemente chiamare std::abort()(potrebbe essere lo stesso su Linux)


Quale biblioteca?
Alex

Fa parte della libreria C ++ standard ed è multipiattaforma in cui esistono compilatori conformi a C ++ 11. Ciò, tuttavia, solleva SIGABRT, che non è davvero un segnale appropriato da sollevare in questo caso.
Benjamin Crawford Ctrl-Alt-Tut
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.