Inspection du contenu du conteneur standard (std :: map) avec gdb

93

En supposant avoir quelque chose comme ça:

#include <map>
int main(){
    std::map<int,int> m;
    m[1] = 2;
    m[2] = 4;
    return 0;
}

Je voudrais pouvoir inspecter le contenu de la carte exécutant le programme depuis gdb.
Si j'essaye d'utiliser l'opérateur d'indice, j'obtiens:

(gdb) p m[1]
Attempt to take address of value not located in memory.

L'utilisation de la méthode find ne donne pas de meilleurs résultats:

(gdb) p m.find(1)
Cannot evaluate function -- may be inlined

Y a-t-il un moyen d'accomplir cela?

Paolo Tedesco
la source

Réponses:

35

Je pense qu'il n'y en a pas, du moins pas si votre source est optimisée, etc. Cependant, il existe des macros pour gdb qui peuvent inspecter les conteneurs STL pour vous:

http://sourceware.org/ml/gdb/2008-02/msg00064.html

Cependant, je ne l'utilise pas, donc YMMV

jpalecek
la source
1
Merci pour le lien; la seule chose est que les macros dépendent de la version des bibliothèques stl, ce que je préférerais éviter. +1
Paolo Tedesco
C'est aussi un peu frustrant que des commandes comme "plist foo std :: string" donnent des erreurs de syntaxe. Il semble que value_type ne puisse contenir aucune ponctuation.
Bklyn
2
Je n'ai pas essayé, mais si cela fonctionne de la même manière que le reste de GDB, mettre le nom avec un nom ponctué entre guillemets simples devrait le faire.
jpalecek
2
Remarque: la fonctionnalité std :: map de ces scripts suppose des types de pointeurs 32 bits. Pour les machines 64 bits, remplacez "+ 4" par "+ 8" partout dans le fichier.
Kyle Simek
pvector n'est pas défini dans mon gdb (version 7.5.91.20130417-cvs-ubuntu).
Jeff
91

Les réponses existantes à cette question sont très dépassées. Avec une récente GCC et GDB Works It Just TM grâce au support de Python intégré dans GDB 7.x et libstdc ++ imprimantes jolies qui viennent avec GCC.

Pour l'exemple de l'OP, j'obtiens:

(gdb) print m
$1 = std::map with 2 elements = {[1] = 2, [2] = 4}

Si cela ne fonctionne pas automatiquement, vous voyez le premier point sur la page Support STL du wiki GDB.

Vous pouvez également écrire de jolies imprimantes Python pour vos propres types, voir Pretty Printing dans le manuel GDB.

Jonathan Wakely
la source
2
Oui, mais d'autres questions sont fermées en tant que doublons, donc je voulais qu'elle contienne des informations récentes.
Jonathan Wakely
1
J'utilise GDB 7.2 et ce qui précède fonctionne ... si vous avez une petite collection. Je n'ai toujours pas trouvé de moyen d'imprimer l'élément 1543 à partir d'un vecteur 4K, autre que de recourir à l'utilisation de structures internes de l'implémentation STL.
pavon
5
Oui, dans GDB 7.2 et le compilateur icpc, j'obtiens l'erreur Could not find operator[].
pavon
11
Malheureusement, cela ne fonctionne pas simplement dans toutes les distributions. Il n'est pas installé par défaut dans Ubuntu 13.10 et il y a des problèmes lorsque vous essayez de l'installer manuellement
nietaki
1
@razeh, Fedora, RHEL (et clones RHEL). Un correctif est en cours pour que les imprimantes fonctionnent également sur les distributions où GDB est lié à Python 3
Jonathan Wakely
25

Il y a toujours une évidence: définissez votre propre fonction de test ... Appelez-la depuis gdb. Par exemple:

#define SHOW(X) cout << # X " = " << (X) << endl

void testPrint( map<int,int> & m, int i )
{
  SHOW( m[i] );
  SHOW( m.find(i)->first );
}

int
main()
{
    std::map<int,int> m;
    m[1] = 2;
    m[2] = 4;
    return 0;  // Line 15.
}

Et:

....
Breakpoint 1 at 0x400e08: file foo.C, line 15.
(gdb) run
Starting program: /tmp/z/qD 

Breakpoint 1, main () at qD.C:15
(gdb) call testPrint( m, 2)
m[i] = 4
(*m.find(i)).first = 2
(gdb) 
Monsieur Ree
la source
16
tant que le processus est en cours d'exécution. pas si utile pour les core-dumps.
sean riley
2
C'est un conseil utile pour déboguer GDB en général, pas seulement avec STL. Je garde toute une bibliothèque de fonctions d'assistance gdb pour beaucoup de données difficiles à récupérer, par exemple write_cuda_array_as_image (). Notez que certains compilateurs suppriment toutes les fonctions qui ne sont pas appelées, donc je place un appel à chaque fonction d'assistance après le "return 0;" de mon principal. Les déclarer également avec extern "C" facilite leur appel depuis gdb.
Kyle Simek
21

le stl-views.gdb habitude d'être la meilleure réponse était, mais pas plus.

Ce n'est pas encore intégré dans la ligne principale GDB, mais voici ce que vous obtenez en utilisant la branche 'archer-tromey-python' :

(gdb) list
1   #include <map>
2   int main(){
3       std::map<int,int> m;
4       m[1] = 2;
5       m[2] = 4;
6       return 0;
7   }
(gdb) break 6
Breakpoint 1 at 0x8048274: file map.cc, line 6.
(gdb) run

Breakpoint 1, main () at map.cc:6
6       return 0;
(gdb) print m
$1 = std::map with 2 elements = {
  [1] = 2,
  [2] = 4
}
(gdb) quit
Employé russe
la source
12

Essayez de dé-référencer les conteneurs STL: sur cette page: http://www.yolinux.com/TUTORIALS/GDB-Commands.html

anand
la source
Celles-ci semblent être l'affaire!
Richard Corden
Ce sont en fait les mêmes macros que dans la réponse précédente :) Je crains qu'il n'y ait pas de solution plus simple.
Paolo Tedesco
Quelle est la commande? Vous avez réussi à nous faire fonctionner hors site avec une grande quantité d'informations non pertinentes. Je ne suis pas intéressé par "Comment démarrer GDB" et les autres.
jww
1

Les réponses ci-dessus fonctionnent et très bien. Si vous utilisez stl-views.gdb, voici la bonne façon d'afficher les cartes et les éléments qu'il contient. Laissez votre carte est la suivante: std::map<char, int> myMap;

(gdb) pmap myMap char int

c'est- pmap <variable_name> <left_element_type> <right_element_type>à- dire pour voir les éléments de la carte.

J'espère que cela pourra aider.

Mazhar MIK
la source
0

Vous pouvez contourner le deuxième problème ( Cannot evaluate function -- may be inlined) en vous assurant que votre compilateur utilise les informations de débogage DWARF-2 (ou 3 ou 4) lorsque vous compilez votre programme. DWARF-2 inclut des informations intégrées, vous devriez donc pouvoir utiliser l'une des méthodes que vous avez décrites pour accéder aux éléments de votrestd::map conteneur.

Pour compiler avec les informations de débogage DWARF-2, ajoutez l' -gdwarf-2indicateur à votre commande de compilation.

Dan
la source
1
Euh, savoir où une fonction a été insérée ne permet pas à GDB d'évaluer les appels à cette fonction; GDB a vraiment besoin d'accéder à une copie hors ligne de la fonction!
SamB