2016-09-24 4 views
20

Я пытаюсь использовать LLDB в Xcode 8 для отладки самого базового STL. Я имел обыкновение печатать такой вектор:Печать/отладка libC++ STL с XCode/LLDB

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++ ??

+0

Вы компилировались с информацией об отладке? Можете ли вы предоставить автономный репродуктор? – EricWF

+1

Конечно, информация об отладке включена. :) Вот глупый проект, который может воспроизвести проблему. Просто установите точку останова в строке std :: cout и запустите команду lldb «p myVector [0]», когда она попадает. Вы получите сообщение об ошибке. Если вы сделаете «p myVector .__ begin_ [0]», он будет хорошо печататься. https://www.dropbox.com/s/ntjywxabxj3e4mc/Crap.zip?dl=0 – cjserio

ответ

47

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

Если вы хотите увидеть элементы в этом векторе, вы можете использовать lldb «Форматы данных STL», чтобы сделать эту работу за вас. Они знают, как выкладываются большинство типов 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> >) $0 = 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) 

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

(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 

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

template class std::vector<MyClass> 

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

+1

Очень тщательный ответ Джим, я ценю это! – cjserio

+0

Закладка этого. Очень полезно! –

+0

Я наблюдаю то же поведение в Linux (Ubuntu 16.10) с clang/lldb 3.9. Но gcc/gdb не имеют проблем с '(gdb) p my_vec [0]'. Интересно, что они делают по-другому. –