GDBの「メモリアクセス」にブレークポイントを設定できますか?


244

gdbを介してアプリケーションを実行していて、特定の変数がアクセスまたは変更されるたびにブレークポイントを設定したい。これを行うための良い方法はありますか?また、C / C ++で変数を監視して、いつ変化するかを確認する他の方法にも興味があります。

回答:


286

watchは書き込み時にのみブレークし、rwatchは読み取り時にブレークし、awatchは読み取り/書き込み時にブレークします。

メモリ位置に読み取りウォッチポイントを設定できます。

gdb$ rwatch *0xfeedface
Hardware read watchpoint 2: *0xfeedface

しかし、1つの制限がrwatchおよびawatchコマンドに適用されます。式でgdb変数を使用することはできません。

gdb$ rwatch $ebx+0xec1a04f
Expression cannot be implemented with read/access watchpoint.

そのため、自分で拡張する必要があります。

gdb$ print $ebx 
$13 = 0x135700
gdb$ rwatch *0x135700+0xec1a04f
Hardware read watchpoint 3: *0x135700 + 0xec1a04f
gdb$ c
Hardware read watchpoint 3: *0x135700 + 0xec1a04f

Value = 0xec34daf
0x9527d6e7 in objc_msgSend ()

編集:ああ、ところで。ハードウェアまたはソフトウェアのサポートが必要です。ソフトウェアは明らかにはるかに遅いです。OSがハードウェアウォッチポイントをサポートしているかどうかを確認するには、can-use-hw-watchpoints環境設定を確認します。

gdb$ show can-use-hw-watchpoints
Debugger's willingness to use watchpoint hardware is 1.

7
C ++メソッドのメンバーを監視したい場合は、このバリアントが非常に役立つことがわかりましたwatch -location mTextFormatted
IvanVučica、

変数のアドレスがない場合はどうなりますか?名前だけを使用できますか?
Raffi Khatchadourian、2011年

5
GDBに、address-of演算子を使用して変数のアドレスを出力させることができます。print &variable
Loduwijk

1
この回答は、コマンドによって監視されているメモリ位置のサイズについては何も述べていませんwatch。一方、これは上記を読んだ後に思い浮かぶ最初の質問です。rwatch *0xfeedface実際に何バイトを監視しますか?
AnT 2015年

8
@AnT、私はそれが1バイトを監視することを想定していましたが、それは特定のタイプにキャストできます。たとえばrwatch *(int *)0xfeedface、それはsizeof(int)バイトを監視します:sourceware.org/gdb/onlinedocs/gdb/Set-Watchpoints html
asksol

28

探しているものをウォッチポイントと呼びます。

使用法

(gdb) watch foo変数の値を監視する foo

(gdb) watch *(int*)0x12345678アドレスが指す値を監視し、必要なタイプにキャストします

(gdb) watch a*b + c/d:プログラムの母国語で有効な、任意に複雑な式を見る

ウォッチポイントには次の3種類があります。

  • watch:gdbは書き込みが発生すると壊れます
  • rwatch:gdbは読み取りが発生すると発生します
  • awatch:gdbはどちらの場合でも壊れます

必要に応じて、より適切なものを選択できます。

詳細については、チェックこれを行います。


5
既存の答えは私にはそれほど簡単に思えなかったので、私は別の答えを書きました...
Paolo M

25

最初の答えがCのような構文を参照していると仮定すると、(char *)(0x135700 +0xec1a04f)行う答えrwatch *0x135700+0xec1a04fは正しくありません。正しい構文はrwatch *(0x135700+0xec1a04f)です。

そこに欠け()ていると、自分でウォッチポイントを使用しようとすると、かなりの苦痛が生じました。


9

私は次のことを試しました:

 $ cat gdbtest.c
 int abc = 43;

 int main()
 {
   abc = 10;
 }
 $ gcc -g -o gdbtest gdbtest.c
 $ gdb gdbtest
 ...
 (gdb) watch abc
 Hardware watchpoint 1: abc
 (gdb) r
 Starting program: /home/mweerden/gdbtest 
 ...

 Old value = 43
 New value = 10
 main () at gdbtest.c:6
 6       }
 (gdb) quit

したがって、それは可能であるように見えますが、ハードウェアのサポートが必要なようです。


プラットフォームがハードウェアウォッチポイントをサポートしていない場合、gdbはソフトウェアウォッチポイントにフォールバックする必要があります。
2013年

2

前述のように、watchを使用して変数がいつ書き込まれたかを確認し、rwatchを使用してそれを読み取り、awatchを使用して読み取り/書き込みを行ったときに確認します。ただし、このコマンドを使用するには、プログラムを中断する必要があり、プログラムを中断したときに変数がスコープ内にある必要があることに注意してください。

watchコマンドを使用します。watchコマンドの引数は、評価される式です。これは、ウォッチポイントを設定するバリアベルが現在のスコープ内にある必要があることを意味します。したがって、非グローバル変数にウォッチポイントを設定するには、変数がスコープ内にあるときにプログラムを停止するブレークポイントを設定しておく必要があります。プログラムが中断した後にウォッチポイントを設定します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.