Xcode 8内でLLDBを使用して、非常に基本的なSTLをデバッグしようとしています。以前は、次のようなベクターを印刷できました。
p myvector[0]
最初のベクトルインデックスにあるものを確認します。これを行うと、次のエラーが表示されます。
error: Couldn't lookup symbols:
__ZNSt3__16vectorI9my_classNS_9allocatorIS1_EEEixEm
代わりに、これを入力する必要があります。
p myvector.__begin_[0]
出力を取得するため。
LLDB svnリポジトリからlibcxx.pyおよびunordered_multi.pyスクリプトをインポートしようとしましたが、何も変わらないようです。
誰もがlibc ++でLLDBから有用な出力を得ることができましたか?
[]
はstd::vector
の演算子メソッドであるため、目的の式を出力するには、lldbが[]
メソッドを呼び出せる必要があります。ここでの問題は、OS XのSTLは可能な限りすべてをインライン化することに積極的であり、同じ関数の行コピーから生成されるスペースを無駄にしないことです。これは最適化されたコードには適していますが、デバッガーに呼び出す[]
演算子がないため、デバッグにはあまり適していません。それはあなたが見ているエラーメッセージです。
このベクター内の要素のみを表示する場合は、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> >) $0 = size=2 {
[0] = (var1 = 10, var2 = 20)
[1] = (var1 = 10, var2 = 20)
}
また、別のコマンド"frame variable"があります。このコマンドは、静的オブジェクトを検査し、データフォーマッターにフックします。関数を呼び出したり、他のより複雑な式パーサータスクを実行することはできませんが、STLデータフォーマッターを使用して個々の要素を取得する方法は知っています。
(lldb) frame var my_vec[1]
(Foo) my_vec[1] = (var1 = 10, var2 = 20)
フレーム変数の-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 = 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) $0 = (x = 0)
ビンゴ!!関数はTEXTブロックに存在しますか?
(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
よくわかりませんが、これは以前に学びました。実稼働段階ではなく、デバッグ段階。テンプレートの関数内の行にブレークポイントを設定した場合、デバッガーは何をしますか?ブレークポイントを設定し、実際にいくつかの既存のアセンブラーコードをトラップまたはジャンプに置き換えます。または、関数に単一のブレークポイントを設定するだけですか?テンプレートとして書かれています。したがって、生産段階でインライン化する必要があります。ただし、デバッグ段階では、関数はインライン化されず、通常の関数として記述されます。ここで言っていることを単純に信じないでください。ご自身で確認してください。 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>
で次のように定義されています。
#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
私はその助けと誰かがもっと深く調べることを願っています。