Impresión / Depuración de libc++ STL con XCode / LLDB


Estoy tratando de usar LLDB dentro de Xcode 8 para depurar STL muy básico. Solía ser capaz de imprimir un vector como este:

p myvector[0]

Para ver lo que estaba en el primer índice vectorial. Ahora cuando hago eso, obtengo este error:

error: Couldn't lookup symbols:
  __ZNSt3__16vectorI9my_classNS_9allocatorIS1_EEEixEm

En su lugar, tengo que escribir esto:

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

He intentado importar el libcxx.py y unordered_multi.py scripts del repositorio svn de LLDB pero eso no parece cambiar nada.

¿Alguien ha sido capaz de obtener cualquier salida útil de LLDB con ¿libc++??

Author: cjserio, 2016-09-24

2 answers

[] es un método de operador en std::vector, por lo que para imprimir la expresión que desea, lldb tendría que ser capaz de llamar al método []. El problema aquí es que el STL en OS X es agresivo acerca de incrustar todo lo que puede, y no desperdiciar espacio produciendo copias fuera de línea de las mismas funciones. Eso es genial para el código optimizado, pero no tan bueno para la depuración porque deja al depurador sin operador [] para llamar. Ese es el mensaje de error que está viendo.

Si solo quieres para ver los elementos en este vector, puede utilizar el lldb "STL data formatters" para hacer este trabajo por usted. Saben cómo se presentan la mayoría de los tipos STL y pueden imprimir los elementos de la mayoría de los tipos de contenedores. Por ejemplo:

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

Pero:

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

También hay otro comando "frame variable" que puede inspeccionar objetos estáticos, y se engancha en los formateadores de datos. No puede llamar a funciones y hacer otras tareas más complejas del analizador de expresiones, pero sí sabe cómo para utilizar los formateadores de datos STL para recuperar elementos individuales:

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

Incluso puede usar la opción de frame var -L para localizar los elementos del vector, y luego puede convertir la dirección para pasarla a otras funciones:

(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

Otra forma de solucionar esto para la depuración - si está utilizando C++11-es poniendo:

template class std::vector<MyClass>

En su código en algún lugar. Esto le indicará al compilador que emita copias fuera de línea de todas las funciones de plantilla para esta especialización. Esa no es una gran solución general, y solo quieres hacerlo para compilaciones de depuración, pero te permite llamar a estas funciones y usarlas en expresiones complejas.

 61
Author: Jim Ingham,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-11 07:11:52

El problema similar también sucede conmigo: error: Couldn't lookup symbols:

Mi solución es usar explícitamente la función cuestionada en algún lugar de un código fuente.

#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
}

Establezca un punto de interrupción en la línea de 1; y ejecútelo.

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

(lldb) p b[0]
(XXX) $0 = (x = 0)
¡Bingo!! ¿Existe la función en un bloque de TEXTO?
(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

No estoy seguro, pero había aprendido esto antes. En una etapa de depuración, en lugar de la etapa de producción. Si establecemos un punto de interrupción en una línea en una función de una plantilla, ¿qué haría un depurador? ¿Estableciendo puntos de interrupción, en realidad reemplazando algún código ensamblador existente con trap o jump, aquí y allá donde se aplica la plantilla? ¿O simplemente establecer un único punto de interrupción en una función? Está escrito como una plantilla. Por lo tanto, debería insertarse en una etapa de producción. En una etapa de depuración, sin embargo, la función no está entre líneas y escrita como una función normal. Por favor, no se limiten a creer lo que digo aquí. Por favor confirme usted mismo. Consultar documentación de gcc, clang, y lldb.

#include <vector> de macOS 10.13.6, Xcode Versión 9.4.1 tiene una 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];
}

El _LIBCPP_INLINE_VISIBILITY se define en #include <__config> como:

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

Tales palabras clave hidden y __always_inline__ parecen controlar el comportamiento.

Cuando agregué inline _LIBCPP_INLINE_VISIBILITY al código de solución de muestra anterior:

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

Resultó en:

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

Espero que la ayuda y alguien investiguen mucho más profundamente.

 0
Author: Tora,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-09 11:46:07