データブレークポイントがあることを知りました。過去 5 年間、Visual Studio を使用して C++ で作業してきましたが、データ ブレークポイントを使用したことはありません。
データブレークポイントとは何か、それらをいつ使用するか、VSでどのように使用するかについて、誰かが光を当てることができますか?
私の理解では、変数の値の変更を確認したいときにデータブレークポイントを設定できます。この場合、変数値の条件でデータ ブレークポイントを設定できます。
他の例はありますか?
データブレークポイントがあることを知りました。過去 5 年間、Visual Studio を使用して C++ で作業してきましたが、データ ブレークポイントを使用したことはありません。
データブレークポイントとは何か、それらをいつ使用するか、VSでどのように使用するかについて、誰かが光を当てることができますか?
私の理解では、変数の値の変更を確認したいときにデータブレークポイントを設定できます。この場合、変数値の条件でデータ ブレークポイントを設定できます。
他の例はありますか?
古き良きDanielLeCheminantは、データブレークポイントの機能について確かな答えを持っているので、有用な使用法を強調するいくつかの逸話を紹介します。
何が変更されるかはわかっているが、それを変更するコードがどこにあるのかほとんどまたはまったくわからないシナリオ(それ以外の場合は、条件付きブレークポイントを使用できます)。具体的には、
「不可能な」シナリオX
-変数がであるためにプログラムがクラッシュしているのに、変数をに設定するコードがないためNULL
に変数を使用してX
はならない場合。を初期化するコードに通常のブレークポイントを設定し、ヒットしたときに、への変更を監視するデータブレークポイントを設定します。やや一般的なのは、メモリの解放が早すぎて、それへのポインタがまだ残っている場合です。データブレークポイントを使用して、誰がメモリを解放しているかを調べます。NULL
X
NULL
X
NULL
面倒なシナリオ-サードパーティのライブラリがデータ構造に悪い、厄介な、恐ろしいことをしている。誰かがあなたのデータをゴミ箱に入れており、明らかにあなたのコードは完璧なので、あなたはそれが起こっていることを知っています。しかし、どこで、いつかはわかりません。確かに、1メガバイトの分解されたDLLをシングルステップで実行できます...しかし、データにデータブレークポイントを設定し、座って、データが破棄されるのを待つことができるのに、なぜわざわざする必要がありますか。
Heisenbugs-不可能なシナリオに似ていますが、注意深く見ると消えてしまい、通常のブレークポイント(条件付きブレークポイントであっても)は役に立たなくなります。タイミングとユーザー入力に敏感なロジックは、この種のものに対して特に脆弱です。データブレークポイントは、適切なタイミングになるまでデバッガーが実際にブレークする必要がないため、そのとらえどころのないバグが実際に発生したときにのみ変更されるメモリの場所を考え出すことができると仮定すると、データブレークポイントを使用してトラップを設定できます。特異なバグと現行犯でそれをキャッチします。
スパゲッティシナリオ-グローバルデータがどこからでもアクセスされる古い腐ったコードベースで一般的です。ええ、あなたは普通の古い条件付きブレークポイントを使うことができます...しかしあなたはそれらの何百も必要になるでしょう。データブレークポイントを使用すると簡単にできます。
意味:
データ ブレークポイントを使用すると、指定したメモリ位置に格納されている値が変更されたときに実行を中断できます。
MSDN から:方法: データ ブレークポイントを設定します。
メモリ変更ブレークポイントを設定する方法
[デバッグ] メニューから [新しいブレークポイント] を選択し、[新しいデータ ブレークポイント] をクリックします。
—または—</p>
[ブレークポイント] ウィンドウ メニューで、[新規] ドロップダウンをクリックし、[新しいデータ ブレークポイント] を選択します。
[新しいブレークポイント] ダイアログ ボックスが表示されます。
[アドレス] ボックスに、メモリ アドレスまたはメモリ アドレスに評価される式を入力します。たとえば、 &foo は、変数 foo の内容が変更されたときにブレークします。
[Byte Count] ボックスに、デバッガで監視するバイト数を入力します。たとえば、4 を入力すると、デバッガーは &foo で始まる 4 バイトを監視し、これらのバイトのいずれかが値を変更するとブレークします。
[OK] をクリックします。
ここまでで、素晴らしい定義とたくさんの素晴らしい理論的説明ができました。
具体例を挙げてみましょう!
私は現在、かなり大規模で複雑なコードベースに取り組んでいます。コードの 1 ビットに小さな安全な変更を加えたところ、まったく無関係なコードベースのチャンクで、メモリ アロケータでクラッシュが発生し始めました。これは通常、メモリ管理で非常に間違ったことを行っていることを示しています - 二重削除または範囲外の書き込みのいずれかです。
ありがたいことに、このようなことをチェックするデバッグ メモリ マネージャーをオンにするオプションがあります。オンにすると、すぐにメモリ ブロック ガード違反が報告され始めました。これは、何かが範囲外に書き込まれたことを意味します。問題は、このレポートがメモリの割り当てが解除された場合にのみ表示されることです。基本的には、「何かが壊れています。何が原因かわかるといいのですが!」と表示されます。
残念ながら、この特定のメモリ チャンクは、割り当て解除の時点で、文字通り何千もの他のメモリ チャンクとまったく見分けがつきません。幸いなことに、デバッグ フレームワークは各割り当てに連続した ID をタグ付けし、破損したメモリには一貫した ID がありました (興味がある場合は #9667 です)。後でメモリ マネージャーの 1 つのクイック ブレークポイントで、その場所を見つけることができました。メモリが割り当てられました。結局のところ、これもすぐには役に立ちませんでした。
しかし、その時点で、いくつかの重要なコンポーネントがありました。
これにより、その特定のバイトにデータ ブレークポイントを設定し、[go] をクリックして、破損が発生した場所を見つけることができました。
私がやったこと - それは私が現在修正中のオフバイワンエラーにつながりました。
これは、データ ブレークポイントがどのように役立つかを示す具体的な例です。:)
データブレークポイントは、一部のメモリが特定の値に設定されたときに発生するブレークポイントだと思います。たとえば、典型的な for ループで i == 10 のときにブレークポイントを設定して、10 回目の反復後に停止することができます。クラスのメンバーが変更されるのを待つなど、ヒープ上の変数への変更を監視することもできます。