Печать / отладка libc++ STL с помощью XCode/LLDB

Я пытаюсь использовать LLDB в Xcode 8 для отладки очень простой STL. Раньше я мог печатать такой вектор:

p myvector[0]

чтобы увидеть, что было в первом векторном индексе. Теперь, когда я это делаю, я получаю эту ошибку:

error: Couldn't lookup symbols:
  __ZNSt3__16vectorI9my_classNS_9allocatorIS1_EEEixEm

вместо этого я должен ввести это:

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

Я попытался импортировать libcxx.py и unordered_multi.py скрипты из репозитория lldb svn, но это, похоже, ничего не меняет.

кто-нибудь смог получить любой полезный вывод из LLDB с libc++??

2 ответов


[] - это метод оператора std::vector, поэтому для печати выражения, которое вы хотите, lldb должен иметь возможность вызывать [] метод. Проблема здесь в том, что STL на OS X агрессивен в отношении вставки всего, что он может, и не тратит пространство, производя из линейных копий тех же функций. Это здорово для оптимизации кода, но не так хорошо для отладки, потому что отладчик не [] оператор позвонить. Это сообщение об ошибке вы видение.

если вы просто хотите увидеть элементы в этом векторе, вы можете использовать lldb "STL Data formatters" чтобы сделать эту работу для вас. Они знают, как выложены большинство типов STL, и могут печатать элементы большинства типов контейнеров. Например:

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

но:

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

есть еще одна команда "переменные рамки" что может проверить статические объекты, и крюки в форматтеры данных. Он не может позвонить. функции и другие более сложные задачи синтаксического анализа выражений, но он знает, как использовать форматеры данных STL для извлечения отдельных элементов:

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

вы даже можете использовать фрейм var в -L возможность найти элементы вектора, а затем вы можете бросить адрес, чтобы передать его другим функциям:

(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

другой способ обойти это для отладки - если вы используете C++11 - это положить:

template class std::vector<MyClass>

в коде где-то. Что будет компилятор выделяет из строки копирует все функции шаблон для этой специализации. Это не отличное общее решение, и вы хотите сделать это только для отладочных сборок, но это позволяет вызывать эти функции и использовать их в сложных выражениях.


аналогичная проблема также происходит со мной: error: Couldn't lookup symbols:

мое решение-явно использовать опрошенную функцию где-то в исходном коде.

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

установите точку останова на линии 1; и запустите ее.

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

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

Бинго!! Существует ли функция в текстовом блоке?

(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

я не уверен, но я узнал это раньше. На стадии отладки, а не на стадии производства. Если мы установим точку останова на линии в функции a шаблон, что бы сделал отладчик? Установка точек останова, фактически замена некоторого существующего кода ассемблера на trap или jump, здесь и там везде применяется шаблон? Или просто установить одну точку останова в функции? Он написан как шаблон. Поэтому он должен быть встроен в стадию производства. Однако на этапе отладки функция не является встроенной и записывается как обычная функция. Пожалуйста, не просто верьте тому, что я говорю. Пожалуйста, подтвердите сами. Обратитесь к документации gcc, clang, и lldb.

#include <vector> MacOS 10.13.6, Xcode версии 9.4.1 имеет макрос _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 определена в #include <__config> as:

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

такие ключевые слова hidden и __always_inline__ кажется, контролировать поведение.

когда я добавил inline _LIBCPP_INLINE_VISIBILITY к коду решения образца выше:

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

в результате:

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

я надеюсь, что помощь и кто-то заглянуть в гораздо больше глубоко.