Définir le point d'arrêt dans le code C ou C ++ par programme pour gdb sous Linux

105

Comment puis-je définir un point d'arrêt dans le code C ou C ++ par programme qui fonctionnera pour gdb sous Linux?

C'est à 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;
}
J. Polfer
la source
8
Très une note latérale (désolé de pinailler), mais si vous vous inquiétez de la portabilité, vous vous inquiétez probablement aussi de l'exactitude - donc int mainplutôt que void main.
Stuart Golodetz
@Stuart - Corrigé. J'aurais dû le faire il y a quelque temps.
J.Polfer
4
@ J.Polfer: Le return 0n'est pas nécessaire, cependant, et c'est juste du bruit!
Courses de légèreté en orbite

Réponses:

107

Une façon est de signaler une interruption:

#include <csignal>

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

En C:

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

MISE À JOUR : MSDN déclare que Windows ne prend pas vraiment en charge SIGINT, donc si la portabilité est un problème, vous feriez probablement mieux d'utiliser SIGABRT.

Håvard S
la source
Oui, cela devrait fonctionner sur tous les systèmes d'exploitation / compilateurs / débogueurs.
Håvard S
1
Je ne connais pas d'autres débogueurs, mais gdb est assez flexible sur la gestion du signal .
Cascabel
4
Nous avons trouvé SIGTRAP meilleur sur certains Unices
JBRWilkinson
1
sous Windows, MSVC, vous pouvez utiliser __debug_break, DebugBreak ou _asm {int 3}.
Fernando Gonzalez Sanchez
2
@FernandoGonzalezSanchez: en fait le nom de la fonction est __debugbreak()et NON __debug_break() , comme vous pouvez le voir ici
Morix Dev
27

Dans un projet sur lequel je travaille, nous faisons ceci:

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

(Dans notre cas, nous voulions planter dur si cela se produisait en dehors du débogueur, générant un rapport d'erreur si possible. C'est l'une des raisons pour lesquelles nous avons utilisé SIGABRT. Faire cela de manière portative sous Windows, Mac et Linux a pris plusieurs tentatives. Nous nous sommes retrouvés avec quelques #ifdefs, commenté utilement ici: http://hg.mozilla.org/mozilla-central/file/98fa9c0cff7a/js/src/jsutil.cpp#l66 .)

Jason Orendorff
la source
2
Comme d'habitude, les fenêtres ne ressemblent pas aux autres :)
mathk
Est-il possible d'émettre le "signal 0" pour continuer à programmer le programme dans un état de pause? Ce serait bien de pouvoir utiliser «n» ou «s» à partir de ce point, sans qu'un «c» ne soit émis.
Jason Doucette
2
@JasonDoucette Si vous voulez vraiment juste que le programme se mette en pause, vous pouvez ajouter une breakpoint()fonction dans votre programme (elle peut être vide ou simplement contenir une instruction d'impression) et l'ajouter break breakpointà votre ~/.gdbinit.
Jason Orendorff
26

En regardant ici , j'ai trouvé le moyen suivant:

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

Cela me semble un peu hackish. Et je pense que cela ne fonctionne que sur l'architecture x86.

J. Polfer
la source
3
Et uniquement avec les compilateurs prenant en charge la syntaxe d'assemblage AT&T. En particulier, le compilateur de Microsoft ( cl.exe) ne prend pas en charge cette syntaxe, mais utilise une syntaxe différente.
Håvard S
la question portait sur Linux, donc je suppose que nous pouvons supposer que la syntaxe gcc fonctionnera pour x86.
js.
BTW - J'ai essayé ce qui précède sur ma machine x86 et cela a fonctionné. J'étais curieux de savoir s'il y avait une meilleure façon de le faire. On dirait qu'il y en a.
J.Polfer
2
J'utilise mingw sur Windows, donc les autres suggestions ne peuvent pas m'aider. L'augmentation du signal SIGINT met juste fin à l'application, SIGTRAP n'est pas défini dans les en-têtes mingw ... L'utilisation de l'instruction int envoie en fait SIGTRAP et gdb se casse bien sur la ligne appropriée.
Machta
Sous Linux, int 3lève un SIGTRAP.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
12

__asm__("int $3"); devrait marcher:

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
la source
1
J'aime #defineça, pour ne pas avoir à me souvenir de la syntaxe. Je l'ai saupoudré dans tout mon code, parfois à la place de assert(), puisque l'arrêt du débiogueur m'a permis d'examiner toutes les variables et la pile. Et, bien sûr, comme l'affirmer, je n'ai pas à le supprimer pour le code de production
Mawg dit de réintégrer Monica le
Il est intéressant de noter que cela a 10 votes positifs alors que les contraintes de question de "Linux" et "GDB" donnent beaucoup d'options en dehors du recours à l'assemblage, qui devrait toujours être un dernier recours pour la portabilité si rien d'autre. Veuillez consulter certaines des autres réponses.
Benjamin Crawford Ctrl-Alt-Tut
5

Décevant de voir autant de réponses de ne pas utiliser le signal dédié pour les points d' arrêt du logiciel, SIGTRAP:

#include <signal.h>

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

Sur OS X, vous pouvez simplement appeler std::abort()(cela peut être la même chose sous Linux)

dacap
la source
Quelle bibliothèque?
Alex
Cela fait partie de la bibliothèque C ++ standard et est multiplateforme où des compilateurs compatibles C ++ 11 existent. Cela soulève cependant SIGABRT, qui n'est pas vraiment un signal approprié à soulever dans ce cas.
Benjamin Crawford Ctrl-Alt-Tut