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.