Impression / débogage libc++ STL avec XCode / LLDB

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

p myvector[0]

pour voir ce qui était dans le premier indice vectoriel. Maintenant, quand je fais cela, je reçois cette erreur:

error: Couldn't lookup symbols:
  __ZNSt3__16vectorI9my_classNS_9allocatorIS1_EEEixEm

a la place, je dois taper ceci:

p myvector.__begin_[0] in order to get any output.

j'ai essayé d'importer le libcxx.py et unordered_multi.py des scripts du dépôt svn LLDB, mais cela ne semble rien changer.

est-ce que quelqu'un a pu obtenir sortie utile de LLDB avec libc++??

30
demandé sur cjserio 2016-09-24 22:48:20

2 réponses

[] est une méthode de l'opérateur sur std::vector, donc pour imprimer l'expression que vous voulez, lldb devrait pouvoir appeler le [] méthode. Le problème ici est que le STL sur OS X est agressif à l'idée de tout contrôler et de ne pas gaspiller de l'espace pour produire des copies hors ligne des mêmes fonctions. C'est génial pour le code optimisé, mais pas aussi bon pour le débogage parce qu'il laisse le débogueur sans [] opérateur d'appel. C'est le message d'erreur que vous voir.

si vous voulez juste voir les éléments dans ce vecteur, vous pouvez utiliser le lldb "STL formateurs" pour faire ce travail pour vous. Ils savent comment la plupart des types de STL sont disposés, et peuvent imprimer les éléments de la plupart des types de conteneur. Par exemple:

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

mais:

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

Il y a aussi une autre commande "cadre " variable" qui peut inspecter les objets statiques, et les crochets dans les formateursde données. Il ne peut pas appeler fonctions et d'autres plus complexes analyseur d'expression de tâches, mais il sait comment utiliser la STL de données des formateurs pour en extraire des éléments:

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

Vous pouvez même utiliser un cadre de var -L option pour localiser les éléments du vecteur, et puis vous pouvez lancer les adresse pour passer à 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

une autre façon de contourner cela pour le débogage - si vous utilisez C++11 - est de mettre:

template class std::vector<MyClass>

dans votre code quelque part. Que donnera instruction 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 ne voulez le faire que pour les constructions de débogage, mais cela vous permet d'appeler ces fonctions et de les utiliser dans des expressions complexes.

61
répondu Jim Ingham 2017-10-11 07:11:52

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

ma solution est d'utiliser explicitement la fonction interrogée quelque part dans un code source.

#include <vector>

template<typename T>
struct Vector : std::vector<T>
{
    Vector(size_t n)
    : std::vector<T>{n}
    {}

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

struct XXX
{
    int x;
};

void func()
{
    std::vector<XXX> a{10};
    Vector<XXX> 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 de rupture sur la ligne de 1; et lancez-le.

(lldb) p a[0]
error: Couldn't lookup symbols:
  __ZNSt3__16vectorI3XXXNS_9allocatorIS1_EEEixEm

(lldb) p b[0]
(XXX)  = (x = 0)

Bingo!! La fonction existe dans un bloc de TEXTE?

(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<XXX>::operator[](unsigned long) at main.cpp:19

Je n'en suis pas sûr, mais j'avais déjà appris cela auparavant. Dans une étape de débogage, au lieu d'une étape de production. Si nous définissons un point de rupture sur une ligne dans une fonction de template, Que ferait un débogueur? Définir des points de rupture, remplacer en fait un code assembleur existant par trap ou jump, ici et là où le modèle est appliqué? Ou tout simplement définir un point de rupture unique dans une fonction? Il est écrit comme un modèle. Elle devrait donc être intégrée dans une phase de production. Un débogage stade, cependant, la fonction n'est pas incorporé et écrit comme une fonction normale. Ne croyez pas simplement ce que je dis ici. Merci de confirmer par vous-même. Consulter la documentation gcc,clang, et lldb.

#include <vector> de MacOS 10.13.6, la Version 9.4.1 de Xcode a une macro _LIBCPP_INLINE_VISIBILITY:

template <class _Tp, class _Allocator>
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];
}

_LIBCPP_INLINE_VISIBILITY est défini à #include <__config> comme:

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

tels mots-clés hidden et __always_inline__ semblent contrôler son comportement.

Quand j'ai ajouté inline _LIBCPP_INLINE_VISIBILITY pour la solution de l'échantillon de code ci-dessus:

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

a entraîné dans:

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

j'espère que l'aide et quelqu'un look beaucoup plus profondément.

0
répondu Tora 2018-09-09 11:46:07