今回も適度になんかしゃべろう~ _(:3 」∠ )_ゴロンゴロン
■今回のデーマはGDBでw
システムやgdbを疑い出したら死亡フラグ。そんなことは絶対にない!
ディスアセンブルしたり、カーネルのソース追いかけたり、サンプルソース作ったり…手段を駆使する前に以下を読め!
●一度冷静になってから、全ての手順を再確認せよ。 ←一番大事!これによっては以下の確認も不要かも・・
●gdbの挙動がおかしい?
そのバイナリとgdb繋いでるプロセスは本当に同一か?make install忘れてないか?
リンクだったり、コピーだったり。別のディレクトリだったり、対向マシンの同じディレクトリだったり。
稼働中プロセスに別のmapをあてはめてデバッガ起動したら、そりゃおかしいわな。
ソース更新したのに挙動が変わらなければ、いつもの俺なら、ちゃんと疑うよね?w
●straceで何も出なくておかしい?
落ち着け。マルチスレッドならオプション要るよね。 ←よくこういう風に自分に問いかけてるので無視~w
⇒ついでに fork追跡に関して、、
set follow-fork-mode <parent|child|ask>
parentは親を、childは子をデバッグする。askはどっちにするか聞いてくれる。
指定した方にはブレイクが残る。他方はブレイク解除される。
●STLの挙動がおかしい?
ロックとらずにSTL持ってるオブジェクトをコピーしてないか?引数渡しでの暗黙のコピーとか。
やはり当たり前の話ばかりだよね(◍′ω‵◍;)
うんじゃ、下ネタはこの辺にして、別物を見てみよう~
■boost::anyの見方 ←なんでも格納できるクラスで意外と使えるw
先に結論を言うと、p (対象の型)*(対象のcontent + 1) で表示できる。
string型を格納したboost::any infoなら、p (string)*(info.content + 1)となる。
確認用サンプルソース
boost::any dataArray[26];
std::string str_data[] = {"aa", ... };
dataArray[0] = str_data[0];
この行を実行した後、dataArray[0]に"aa"がちゃんと入っているか確認してみよう~
(gdb) p dataArray[0]
$1 = {content = 0x8c170c0} #contentというメンバがあるんだな
(gdb) p dataArray[0].content #そのcontentを表示してみる
$2 = (class boost::any::placeholder *) 0x8c170c0
(gdb) p *dataArray[0].content #アドレスらしいから*付けてみる
warning: RTTI symbol not found for class 'boost::any::holder<std::string>'
$3 = {_vptr.placeholder = 0x805aef8} #めげそう…だが先頭が仮想関数テーブルであることは分かる。
(gdb) ptype dataArray[0] #とりあえず型を調べることにする。
type = class boost::any {
private:
class boost::any::placeholder *content;
(以下略)
(gdb) ptype *dataArray[0].content #*contentも型を調べてみる
type = class boost::any::placeholder {
public:
~placeholder(int);
virtual const struct std::type_info & type() const;
virtual class boost::any::placeholder * clone() const;
}
やはり仮想関数がある。ってことは先頭1ワードは仮想関数テーブルだから実体は次のアドレスに格納されている。たぶん。
+1(ポインタだから実際には4バイト加算)したアドレスをstringでキャストして表示してみる。
(gdb) p (string)*(dataArray[0].content + 1)
$6 = {static npos = 4294967295, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>},
_M_p = 0x8c16e54 "aa"}} #ビンゴ!あったぞ
ちなみに、コピーして代入したはずなのに、元データ(str_data[0])の実体と同じアドレスを指しているが、問題ない。
STLは効率化のため、値を書き換えない間は同じ実体を参照する仕組みだからね。
(gdb) p str_data[0]
$11 = {static npos = 4294967295, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>},
_M_p = 0x8c16e54 "aa"}} #コピーしたdataArray[0]の方と同じアドレス
(gdb) p (*rcv_msg.pimpl).apu_id.pimpl.m_serviceSupplierNumber
There is no member or method named m_serviceSupplierNumber.
(gdb) p/x (*(*rcv_msg.pimpl).apu_id.pimpl).m_serviceSupplierNumber
$24 = 0x2c0000 (gdb) p/x (*(*rcv_msg.pimpl).apu_id.pimpl).binary
$25 = {<std::_Vector_base<unsigned char,std::allocator<unsigned char> >> =
{
_M_impl = {<std::allocator<unsigned char>> = {<__gnu_cxx::new_allocator<unsigned char>> = {<No data fields>}, <No data fields>}, _M_start = 0x872b4c0, _M_finish = 0x872b4c8,
_M_end_of_storage = 0x872b4c8}}, <No data fields>
(gdb) p msg->getCommonHeader().get_message_type()
(gdb) p *msg->getCommonHeader().pimpl メソッドは呼べる。
(๑¯ω¯๑)終わり~