Imprimer / déboguer libc ++ STL avec XCode / LLDB

J’essaie d’utiliser LLDB dans Xcode 8 pour déboguer une STL très basique. J’avais l’habitude d’imprimer un vecteur comme celui-ci:

p myvector[0] 

pour voir ce qui était dans le premier index vectoriel. Maintenant, quand je fais ça, j’obtiens cette erreur:

 error: Couldn't lookup symbols: __ZNSt3__16vectorI9my_classNS_9allocatorIS1_EEEixEm 

Au lieu de cela, je dois taper ceci:

 p myvector.__begin_[0] 

afin d’obtenir une sortie.

J’ai essayé d’importer les scripts libcxx.py et unordered_multi.py à partir du référentiel LLDB svn mais cela ne semble rien changer.

Quelqu’un a-t-il pu obtenir une sortie utile de LLDB avec libc ++?

[] est une méthode opérateur sur std::vector . Par conséquent, pour imprimer l’expression que vous voulez, lldb doit pouvoir appeler la méthode [] . Le problème ici est que la STL sous OS X s’acharne à tout aligner, et à ne pas gaspiller de l’espace en produisant des copies décalées des mêmes fonctions. C’est excellent pour le code optimisé, mais pas pour le débogage, car il ne laisse aucun opérateur [] appeler. C’est le message d’erreur que vous voyez.

Si vous voulez juste voir les éléments dans ce vecteur, vous pouvez utiliser les “formateurs de données STL” de lldb pour faire ce travail pour vous. Ils savent comment la plupart des types STL sont disposés et peuvent imprimer les éléments de la plupart des types de conteneurs. Par exemple:

 (lldb) expr my_vec[0] error: Couldn't lookup symbols: __ZNSt3__16vectorI3FooNS_9allocatorIS1_EEEixEm 

mais:

 (lldb) expr my_vec (std::__1::vector >) $0 = size=2 { [0] = (var1 = 10, var2 = 20) [1] = (var1 = 10, var2 = 20) } 

Il existe également une autre commande “frame variable” qui peut inspecter des objects statiques et s’accroche aux formateurs de données. Il ne peut pas appeler de fonctions ni effectuer d’autres tâches d’parsing d’expression plus complexes, mais il sait comment utiliser les formateurs de données STL pour récupérer des éléments individuels:

 (lldb) frame var my_vec[1] (Foo) my_vec[1] = (var1 = 10, var2 = 20) 

Vous pouvez même utiliser l’option -L frame var pour localiser les éléments du vecteur, puis transtyper l’adresse pour la transmettre à d’autres fonctions:

 (lldb) frame var -L my_vec[1] 0x0000000100100348: (Foo) my_vec[1] = { 0x0000000100100348: var1 = 10 0x000000010010034c: var2 = 20 } (lldb) expr printf("%d\n", ((class Foo *) 0x0000000100100348)->var1) 10 (int) $3 = 3 

Une autre façon de contourner ce problème pour le débogage (si vous utilisez C ++ 11) consiste à mettre:

 template class std::vector 

dans votre code quelque part. Cela demandera au compilateur d’émettre des copies hors ligne de toutes les fonctions de modèle pour cette spécialisation. Ce n’est pas une bonne solution générale, et vous voulez le faire uniquement pour les versions de débogage, mais cela vous permet d’appeler ces fonctions et de les utiliser dans des expressions complexes.

Le problème similaire se produit également avec moi: error: Couldn't lookup symbols:

Ma solution consiste à utiliser explicitement la fonction en question quelque part dans un code source.

 #include  template struct Vector : std::vector { Vector(size_t n) : std::vector{n} {} T& operator[](size_t n) { return std::vector::operator[](n); } }; struct XXX { int x; }; void func() { std::vector a{10}; Vector b{10}; auto x = b[0]; // gcc will produce an assembler code of operator[] for debug purpose 1; // as a break point } 

Définissez un point d’arrêt sur la ligne 1; et l’exécuter.

 (lldb) pa[0] error: Couldn't lookup symbols: __ZNSt3__16vectorI3XXXNS_9allocatorIS1_EEEixEm (lldb) pb[0] (XXX) $0 = (x = 0) 

Bingo !! La fonction existe-t-elle dans un bloc TEXT?

 (lldb) image lookup -r -n 'XXX.*operator' 1 match found in /Users/xxx/Library/Developer/Xcode/DerivedData/xxx: Address: sandbox[0x00000001000011f0] (sandbox.__TEXT.__text + 256) Summary: sandbox`Vector::operator[](unsigned long) at main.cpp:19 

Je ne suis pas sûr, mais j’avais déjà appris cela. Dans une étape de débogage, au lieu d’une étape de production Si nous définissons un point d’arrêt sur une ligne dans une fonction d’un modèle, que ferait un débogueur? Définir des points d’arrêt, remplacer en réalité un code assembleur existant par trap ou jump, ici et là partout où le modèle est appliqué? Ou simplement définir un point d’arrêt unique dans une fonction? C’est écrit comme un modèle. Donc, il devrait être intégré dans une étape de production. Dans une phase de débogage, cependant, la fonction n’est pas en ligne et écrite comme une fonction normale. S’il vous plaît ne croyez pas simplement ce que je dis ici. S’il vous plaît confirmer par vous-même. Consultez la documentation de gcc, clang, et lldb.

#include de MacOS 10.13.6, Xcode version 9.4.1 comporte une macro _LIBCPP_INLINE_VISIBILITY :

 template  inline _LIBCPP_INLINE_VISIBILITY typename vector<_Tp, _Allocator>::reference vector<_Tp, _Allocator>::operator[](size_type __n) { _LIBCPP_ASSERT(__n < size(), "vector[] index out of bounds"); return this->__begin_[__n]; } 

La _LIBCPP_INLINE_VISIBILITY est définie dans #include <__config> comme:

 #define _LIBCPP_INLINE_VISIBILITY __atsortingbute__ ((__visibility__("hidden"), __always_inline__)) 

De tels mots clés hidden et __always_inline__ semblent contrôler le comportement.

Lorsque j’ai ajouté inline _LIBCPP_INLINE_VISIBILITY à l’exemple de code de solution ci-dessus:

  inline _LIBCPP_INLINE_VISIBILITY T& operator[](size_t n) { return std::vector::operator[](n); } 

abouti à:

 (lldb) pb[0] error: Couldn't lookup symbols: __ZN6VectorI3XXXEixEm 

J’espère que cette aide et quelqu’un approfondiront davantage.