私が取り組んでいるやや大規模なプロジェクトがあり、誰かがこれに似たコードを追加したことを発見しました:
std::cout << std::hex << variable << endl;
すべての cout 呼び出しを調べて、それぞれを手動で調べる以外に、出力ストリームのベースを 16 進数として残した問題のある cout 行を特定する方法はありますか?
ベースを設定するにはさまざまな方法があるようで、単一の関数呼び出しにブレークポイントを設定してもうまくいかないようです。例えば:
... << std::hex << ...
... << setbase(16) << ...
std::cout.setf ( std::ios::hex, std::ios::basefield );
- 等
データブレークポイントを設定できるように、libstdc ++が内部変数を格納するために使用している変数を簡単に知る方法はありますか?
アップデート:
コードをいじってみたところ、perreal と Employed Russian からの両方の回答を部分的に使用して、最終的に解決策を思いつくことができました。これが私がしたことです:
まず、プログラム内に次のコードを追加して、ブレークして関数にステップインし、cout フラグ変数 (_M_flags) のアドレスを取得できるようにしました。
std::ios_base::fmtflags f;
f = std::cout.flags();
2 行目にブレークポイントを設定し、関数にステップインすると、次の libstdc++ コードが得られました。
// [27.4.2.2] fmtflags state functions
/**
* @brief Access to format flags.
* @return The format control flags for both input and output
*/
fmtflags
flags() const
{ return _M_flags; }
残念ながら、gdb はこの変数を出力できませんでしたが、逆アセンブリ ビューに移動することで、_M_flags で使用されているアドレスを特定できました。
x0x84ca2e8 <std::ios_base::flags() const> push %ebp
x0x84ca2e9 <std::ios_base::flags() const+1> mov %esp,%ebp
x0x84ca2eb <std::ios_base::flags() const+3> mov 0x8(%ebp),%eax
>x0x84ca2ee <std::ios_base::flags() const+6> mov 0xc(%eax),%eax
x0x84ca2f1 <std::ios_base::flags() const+9> pop %ebp
x0x84ca2f2 <std::ios_base::flags() const+10> ret
0xc(%eax)
_M_flags のアドレスが含まれていました。
アドレスを取得した後、条件付きハードウェア ウォッチポイントを設定して、16 進ビットがいつ変化するかを確認し、問題のあるコードを追跡するのは簡単でした。
実行時に dlopen を介してロードされた .so オブジェクトが原因であることが判明しました。
問題を解決するために、この質問で参照されているように、Boost IO State Savers を使用することになりました。