›C++【C++】LLDBによる動的な関数呼び出しが出来ない問題と対処【print(p/po)コマンド】C++のクラス・オブジェクトには、LLDBによる関数の動的呼び出しが行えないケースが存在する。targetget関数の実体である_ZN3Foo3getEvシンボルが見つからないというエラーが発生している。原因プログラム内でget関数が一度も使われていないとこの現象が発生する。逆にプログラム内で一度でもget関数が使用されていれば、get関数の実体がコンパイラによって生成され、LLDB側でも問題なく動的な関数呼び出しが行えるようになる。9これはvectorクラス、stringクラスのat関数やその他の一部の関数についても同様の方法で対処が可能である。shared_ptr)のget関数についてはClangのlibc++ライブラリが__attribute__((__always_inline__))オプション(関数を常にインライン化するオプション)を指定している関係で関数の実体が作成されない制限があり、動的呼び出しは常に行えない。加えて、シンボルの可視属性が不可視__visibility__("hidden")に設定されている点にも注意したい。コンパイル時にマクロ定義_LIBCPP_INLINE_VISIBILITYを無効にすればなんとかなるのではないか。ちなみに、上記の制限によって動的な関数呼び出しが行えない場合は、最終手段としてプライベート・メンバ変数を直接参照する方法があるので、万が一のために覚えておくと良いかもしれない。u"ABC"根本原因なお、Foo::get関数の実体が生成されない根本的な原因は、get関数をクラスの宣言部で実装している所にある。宣言部で実装された関数はインライン関数となるため、実体は存在し得ないわけだ。上記の対応方法で生成された実体はおそらくスタックトレース用のものなのであろう。最適化ビルド時やリリースビルド時には生成されない可能性がある。対処方法3つの対処方法がある。対処方法1宣言部で行われていた関数の実装を分離することで対処が可能になる。9ただしinlineキーワードによる関数のインライン化は当然行えなくなる。対処方法2こちらは最終奥義であり、オススメはしない。私はデバッグ中に何度もお世話になったが、あまり他人に勧められるものではない。対象の関数をvirtualキーワードによって仮想関数として宣言すれば、LLDB側でも動的な呼び出しが可能になる。9対処方法3また実体化したい関数が複数になってしまう場合は、対象の関数を呼び出すだけのダミー関数を作成すると良い。8若干面倒ではあるが、実体化したい対象の関数を個別にvirtual修飾するよりは安全で意図も明確になる。オーバーライド時の対応これらのえげつないハックは非オーバーライド関数であれば派生クラス側でも問題なく機能する。9ただ残念ながらオーバーライド時にはエラーになってしまう。evaluation.この場合、基底クラス側に適当な名前でブリッジ用の関数を作成し、そちらを代わりに呼び出すようにすれば良い。