Оценка выражения с перегруженными операторами в С++ lldb

Я отлаживаю программу на С++ в Xcode 5 с помощью lldb, и я хотел бы оценивать произвольные выражения в отладчике, особенно те, которые используют перегруженные операторы.

Например, я создал очень простой проект Xcode 5 С++ со следующими параметрами main.cpp и all для компилятора/компоновщика/etc, установленными по умолчанию:

#include <iostream>
#include <vector>

int main(int argc, const char * argv[])
{
  std::vector<int> vec;
  vec.push_back(42);
  std::cout << "vec[0] = " << vec[0] << std::endl;
  return 0;
}

Я установил точку останова на строке return 0; и запустил программу.

Затем в командной строке lldb печать вектора в целом отлично работает:

(lldb) expr vec
(std::__1::vector<int, std::__1::allocator<int> >) $0 = size=1 {
  [0] = 42
}

Однако я не могу получить доступ к своим членам, используя перегруженный operator[]:

(lldb) expr vec[0]
error: call to a function 'std::__1::vector<int, std::__1::allocator<int> >::operator[](unsigned long)' ('_ZNSt3__16vectorIiNS_9allocatorIiEEEixEm') that is not present in the target
error: The expression could not be prepared to run in the target

Точно так же я не могу получить итератор (хотя у меня меньше опыта здесь, поэтому мой синтаксис может быть неправильным):

(lldb) expr vector<int>::iterator it = vec.begin()
error: use of undeclared identifier 'vector'
error: expected '(' for function-style cast or type construction
error: expected '(' for function-style cast or type construction
error: 3 errors parsing expression

и

(lldb) expr (vector<int>::iterator) vec.begin()
error: use of undeclared identifier 'vector'
error: expected '(' for function-style cast or type construction
error: expected '(' for function-style cast or type construction
error: 3 errors parsing expression

Аналогично, печать простой строки отлично работает:

(lldb) expr string("a")
(std::__1::string) $0 = "a"

Однако простая конкатенация строк не выполняется:

(lldb) expr string("a") + string("b")
error: invalid operands to binary expression ('string' (aka 'std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >') and 'string')
error: 1 errors parsing expression

Что я делаю неправильно? Поддерживает ли lldb оценку с перегруженными операторами?

Заранее благодарю вас!

Ответ 1

Обратите внимание, что стандартные библиотеки С++ настроены таким образом, что они встроят все шаблонные функции, которые могут быть разумно встроены, и нет настоящих функциональных копий. Так, например, когда вы идете на вызов std::vector<int>::begin(), такой функции нет. Все его применения были встроены.

Вот почему вы получаете ошибки о "вызове функции... нет в целевой". Могут быть встроенные копии функции, но мы не можем позвонить. В качестве примера, если я создаю небольшую программу на С++, которая делает std::vector, и нажимает на нее некоторые элементы, а затем выполняет итерацию по ним, а затем делает:

    (lldb) image lookup -r -n begin
    2 matches found in /private/tmp/vector:
        Address: vector[0x0000000100000eaf] (vector.__TEXT.__text + 1071)
        Summary: vector`main + 1071 [inlined] std::__1::vector<int, std::__1::allocator<int> >::begin() at vector.cpp:12
                 vector`main + 1071 at vector.cpp:12        Address: vector[0x0000000100000eaf] (vector.__TEXT.__text + 1071)
        Summary: vector`main + 1071 [inlined] std::__1::vector<int, std::__1::allocator<int> >::begin() at vector.cpp:12
                 vector`main + 1071 at vector.cpp:12

Итак, все экземпляры начального и конечного аксессуаров для std::vector<int> встроены. И далее в части, которая поступает из самой библиотеки std c:

12 matches found in /usr/lib/libc++.1.dylib:
    Address: libc++.1.dylib[0x000000000003e4ec] (libc++.1.dylib.__TEXT.__text + 252188)
    Summary: libc++.1.dylib`std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::begin()        Address: libc++.1.dylib[0x000000000003e51c] (libc++.1.dylib.__TEXT.__text + 252236)
    Summary: libc++.1.dylib`std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::begin() const        Address: libc++.1.dylib[0x000000000003e574] (libc++.1.dylib.__TEXT.__text + 252324)

и еще несколько для basic_string, и все. Поэтому нет реальных реализаций, которые мы можем назвать. Затем, когда у нас есть только реальный мир этих объектов std, доступных нам, мир разваливается другими странными способами, когда вы начинаете нажимать на него.

lldb в настоящее время недостаточно умен, чтобы понять, как восстановить шаблонную функцию/метод из файлов заголовков стандартной библиотеки С++. У нас недостаточно среды, в которой ваш код изначально был скомпилирован для выполнения этой задачи.

Обратите внимание, что это не проблема с перегруженными операторами, это скорее проблема с тем, как библиотеки std используются компилятором. Все должно работать лучше для ваших собственных классов, где при -O0 не так много вложений.

Ответ 2

Я просто столкнулся с той же проблемой и, по-видимому, нашел простую работу. Вы можете получить доступ к i-му элементу вектора vec следующим образом:

(lldb) p vec.__begin_[i]
(int) $1 = 100