Est-il possible dans gdb d’accéder à une ligne avant la ligne en cours d’exécution . Par exemple:
void my_fun( somePtrType** arr,int start,int end)
{
// arr is an array of pointers to somePtrType
//line a
... some assignments
swap(&arr[ind1] , &arr[ind2] ) ;
//line b (current line )
}
Je suis actuellement à la ligne b et peux y examiner les valeurs arr
, mais je souhaite revenir à la ligne a et examiner le contenu de arr
à ce moment-là.
Je pense que cela pourrait ne pas être possible car un débogueur peut exécuter un code au ralenti, mais ne peut pas le faire exécuter à l'envers.
Encore d'autres idées ..
Oui! Avec la nouvelle version 7.0 gdb, vous pouvez faire exactement cela!
La commande serait "reverse-step
" ou "reverse-next
".
Vous pouvez obtenir gdb-7.0 sur ftp.gnu.org:/pub/gnu/gdb
Si vous rencontrez l’erreur: Target child does not support this command.
, essayez d’ajouter target record
au début de l’exécution, après avoir lancé run
.
Edit: Puisque GDB 7.6 target record
est obsolète, utilisez plutôt target record-full
.
Oui, cela est possible et simple maintenant, avec du matériel réel (c'est-à-dire pas uniquement avec une VM) . GDB-7.0 prend en charge le débogage inversé avec des commandes telles que reverse-step et reverse-continue, sur des machines Linux x86 natives.
Il y a un tutoriel ici: http://www.sourceware.org/gdb/wiki/ProcessRecord/Tutorial
Réponse courte : Non.
Pour contournement lire ci-dessous.
Bien qu’à la ligne b, il ne soit pas possible de déterminer la valeur de la ligne a, il est possible de consigner la valeur de arr en a et b et d’autres emplacements en ne touchant qu’un seul point d'arrêt.
(gdb) commande 1
Tapez des commandes pour le moment où le point d'arrêt 1 est atteint, une par ligne. Terminez avec une ligne disant simplement "fin".
continuer
fin
Désormais, lorsque tous les autres points d'arrêt de journalisation sont atteints, la valeur d'arr sera sauvegardée à l'écran, mais le point d'arrêt n'attendra pas l'interaction de l'utilisateur et se poursuivra automatiquement. Lorsque vous frappez un point d'arrêt à la ligne b, vous pouvez voir les valeurs passées d'arr qui seraient enregistrées dans gdb lui-même.
Selon la situation, vous pouvez également vider (et afficher) de nombreuses informations utiles. Par exemple, vous voudrez peut-être aussi vider un compteur de boucle (disons i) si la fonction ci-dessus est appelée 10000 fois dans une boucle. Cela dépend vraiment de ce que vous essayez d’atteindre.
mozilla rr
L’enregistrement et la relecture intégrés de GDB présentent de sérieuses limitations, par exemple: aucune prise en charge des instructions AVX: Le débogage inversé gdb échoue avec "L'enregistrement de processus ne prend pas en charge l'instruction 0xf0d à l'adresse"
Les inconvénients de rr:
L'exemple suivant présente certaines de ses fonctionnalités, notamment les commandes reverse-next
, reverse-step
et reverse-continue
.
Installez Ubuntu 16.04:
Sudo apt-get install rr linux-tools-common linux-tools-generic linux-cloud-tools-generic
Sudo cpupower frequency-set -g performance
Mais envisagez également de compiler à partir des sources pour obtenir les dernières mises à jour, ce n'était pas difficile.
Programme de test:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int f() {
int i;
i = 0;
i = 1;
i = 2;
return i;
}
int main(void) {
int i;
i = 0;
i = 1;
i = 2;
/* Local call. */
f();
printf("i = %d\n", i);
/* Is randomness completely removed?
* Recently fixed: https://github.com/mozilla/rr/issues/2088 */
i = time(NULL);
printf("time(NULL) = %d\n", i);
return EXIT_SUCCESS;
}
compiler et exécuter:
gcc -O0 -ggdb3 -o reverse.out -std=c89 -Wextra reverse.c
rr record ./reverse.out
rr replay
Vous êtes maintenant dans une session GDB et vous pouvez inverser correctement le débogage:
(rr) break main
Breakpoint 1 at 0x55da250e96b0: file a.c, line 16.
(rr) continue
Continuing.
Breakpoint 1, main () at a.c:16
16 i = 0;
(rr) next
17 i = 1;
(rr) print i
$1 = 0
(rr) next
18 i = 2;
(rr) print i
$2 = 1
(rr) reverse-next
17 i = 1;
(rr) print i
$3 = 0
(rr) next
18 i = 2;
(rr) print i
$4 = 1
(rr) next
21 f();
(rr) step
f () at a.c:7
7 i = 0;
(rr) reverse-step
main () at a.c:21
21 f();
(rr) next
23 printf("i = %d\n", i);
(rr) next
i = 2
27 i = time(NULL);
(rr) reverse-next
23 printf("i = %d\n", i);
(rr) next
i = 2
27 i = time(NULL);
(rr) next
28 printf("time(NULL) = %d\n", i);
(rr) print i
$5 = 1509245372
(rr) reverse-next
27 i = time(NULL);
(rr) next
28 printf("time(NULL) = %d\n", i);
(rr) print i
$6 = 1509245372
(rr) reverse-continue
Continuing.
Breakpoint 1, main () at a.c:16
16 i = 0;
selon http://sourceware.org/gdb/current/onlinedocs/gdb.html#SEC51 , et "si l'environnement cible le prend en charge", oui.
Si votre programme est court, le truc habituel est,
r
pour relancer le débogageGDBa été fait pour faire ça!
Si votre code d'installation pour arr est juste au-dessus de "line a" (un scénario très courant), vous pouvez le faire comme ceci:
tbreak myfilename.c:123
(la ligne 123 est le début du code de configuration pour arr), puis
jump 123
Le "tbreak" empêche gdb de continuer (reprendre) le programme après le saut.
alors vous pouvez parcourir le code de configuration ou simplement définir un point d'arrêt sur "ligne a" et continuer
Tout le monde souhaite un débogueur Omniscient comme celui-ci: http://www.lambdacs.com/debugger/ , mais ils sont (selon la langue/la machine) difficiles à créer et ont beaucoup de comptabilité à faire.
Pour le moment, sur du matériel réel et non dans une VM, il est presque impossible de le faire.