GDB: ‘Next’ing automatique?

Rapide cette fois.

Est-il possible (autre que d’appuyer sur Entrée pour toujours) que gdb passe continuellement d’un programme à un autre pour trouver l’emplacement d’un bogue?

Edit: continue n’est pas ce que je voudrais; J’aimerais voir effectivement l’exécution complète du programme, ligne par ligne, comme vous le feriez à maintes resockets.

Voici quelque chose qui est un tel bidouillage que je suis un peu gêné de le publier. Mais si vous n’avez besoin que d’une seule tâche, cela pourrait suffire à vous permettre d’obtenir les informations souhaitées. Il devrait vraiment y avoir un meilleur moyen.

Vous pouvez définir un petit script gdb stupide qui exécute l’ step ou next commande next un certain nombre de fois:

 # file: step_mult.gdb define step_mult set $step_mult_max = 1000 if $argc >= 1 set $step_mult_max = $arg0 end set $step_mult_count = 0 while ($step_mult_count < $step_mult_max) set $step_mult_count = $step_mult_count + 1 printf "step #%d\n", $step_mult_count step end end 

(J'ai utilisé step au lieu de next sans raison particulièrement bonne; changez-le simplement pour ce dont vous avez besoin.)

Ensuite, vous pouvez exécuter cette commande (avec un nombre facultatif) et afficher chaque step ou chaque step correctement.

Voici un exemple de programme qui plantera lorsqu'il tentera de déréférencer un pointeur NULL:

 #include int x[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8,9, 10 }; int* p[11]; int main() { int i; for (i = 0; i < 11; ++i) { p[i] = &x[i]; } p[5] = 0; for (i = 0; i < 11; ++i) { printf( "*p[%d] == %d\n", i, *p[i]); } return 0; } 

Voici une session gdb (sous Windows) pour déboguer ce programme et utiliser le script step_mult :

 C:\temp>gdb test.exe GNU gdb (GDB) 7.2 ... Reading symbols from C:\temp/test.exe...done. (gdb) source c:/temp/step_mult.gdb (gdb) start Temporary breakpoint 1 at 0x401385: file C:\temp\test.c, line 23. Starting program: C:\temp/test.exe [New Thread 5396.0x1638] Temporary breakpoint 1, main () at C:\temp\test.c:23 23 for (i = 0; i < 11; ++i) { (gdb) step_mult 70 step #1 24 p[i] = &x[i]; step #2 23 for (i = 0; i < 11; ++i) { step #3 24 p[i] = &x[i]; step #4 23 for (i = 0; i < 11; ++i) { step #5 24 p[i] = &x[i]; step #6 23 for (i = 0; i < 11; ++i) { step #7 24 p[i] = &x[i]; step #8 23 for (i = 0; i < 11; ++i) { step #9 24 p[i] = &x[i]; step #10 23 for (i = 0; i < 11; ++i) { step #11 24 p[i] = &x[i]; step #12 23 for (i = 0; i < 11; ++i) { step #13 24 p[i] = &x[i]; step #14 23 for (i = 0; i < 11; ++i) { step #15 24 p[i] = &x[i]; step #16 23 for (i = 0; i < 11; ++i) { step #17 24 p[i] = &x[i]; step #18 23 for (i = 0; i < 11; ++i) { step #19 24 p[i] = &x[i]; step #20 23 for (i = 0; i < 11; ++i) { step #21 24 p[i] = &x[i]; step #22 23 for (i = 0; i < 11; ++i) { step #23 27 p[5] = 0; step #24 29 for (i = 0; i < 11; ++i) { step #25 30 printf( "*p[%d] == %d\n", i, *p[i]); step #26 *p[0] == 0 29 for (i = 0; i < 11; ++i) { step #27 30 printf( "*p[%d] == %d\n", i, *p[i]); step #28 *p[1] == 1 29 for (i = 0; i < 11; ++i) { step #29 30 printf( "*p[%d] == %d\n", i, *p[i]); step #30 *p[2] == 2 29 for (i = 0; i < 11; ++i) { step #31 30 printf( "*p[%d] == %d\n", i, *p[i]); step #32 *p[3] == 3 29 for (i = 0; i < 11; ++i) { step #33 30 printf( "*p[%d] == %d\n", i, *p[i]); step #34 *p[4] == 4 29 for (i = 0; i < 11; ++i) { step #35 30 printf( "*p[%d] == %d\n", i, *p[i]); step #36 Program received signal SIGSEGV, Segmentation fault. 0x004013d2 in main () at C:\temp\test.c:30 30 printf( "*p[%d] == %d\n", i, *p[i]); step #37 Program received signal SIGSEGV, Segmentation fault. 0x004013d2 in main () at C:\temp\test.c:30 30 printf( "*p[%d] == %d\n", i, *p[i]); step #38 Program exited with code 030000000005. step #39 The program is not being run. (gdb) 

Malheureusement, comme le script ne s’arrête pas lorsque la erreur de segmentation se produit, gdb décide de simplement arrêter le débogage du programme, de sorte que vous ne pouvez plus effectuer d’informations utiles. Mais le journal peut encore être utile.

Je suis sûr qu'il existe de nombreuses façons de rendre le script plus intelligent. Malheureusement, je ne sais pas comment faire cela, et les documents de niveau utilisateur pour GDB ne semblent pas trop utiles pour ces détails. La meilleure solution serait que le script détecte la erreur de segmentation ou que le signal soit arrivé et arrêtez-vous simplement au lieu de vous fier à un nombre arbitraire. J'imagine que l'interface gdb / MI, ou probablement même l'interface de script Python, pourrait avoir un bon mécanisme, mais je ne sais rien à ce sujet.

Après votre première exécution, vous pouvez utiliser le nombre affiché (37 dans mon exemple), redémarrer le programme et donner un nombre proche de l'endroit où il s'est écrasé et prendre le contrôle manuellement.

Comme je l'ai dit, ce n'est pas particulièrement joli - mais cela pourrait vous mener là .

Vous pouvez utiliser continue ou c pour continuer l’exécution jusqu’au prochain point d’arrêt.

Voir également Exécuter une application dans la BDG jusqu’à ce qu’une exception se produise (StackOverflow) pour savoir comment définir un “point d’arrêt”, qui interrompra l’exécution lorsqu’une exception est levée.

La commande continue sera exécutée jusqu’à ce qu’un point d’arrêt se produise, que l’application provoque une exception (c’est-à-dire un crash) ou que l’application se termine.

  • Référence GDB

Voir aussi cet article: c – Pas automatique GDB – impression automatique des lignes en mode libre? , qui utilise une interface python pour gdb.