.NET Framework デバッグ ~ マネージドコードのメソッド名を指定してブレークポイントを設定する方法

.NET Framework デバッグ ~ 例外オブジェクトの捕まえ方 で使ったコードで、 もう少し遊んでみましょう。

サンプルコードでは button1_Click というメソッドで問題を発生させていました。 そこで、このメソッドにブレークポイントを設定してみましょう。

マネージドコードは基本的に、メソッド毎の JIT コンパイルで実行されます。つまり、 Foo メソッド、Bar メソッドがあったとすると、Foo メソッドが初めて呼び出されたところで初めてコンパイルされて、 呼び出されるのです。この時点で初めてブレークポイントを設定するべきアドレスが決まるわけです。 そのため bp コマンドで直ちにブレークポイントを設定することが出来ません。

ちなみに、Foo メソッドがコンパイルされたからといって、他のメソッドもコンパイルされるわけではありません。 あくまでメソッド毎に JIT コンパイルされます。

JIT 前のブレークポイント設定例

メソッド名でブレークさせるには、!sos.bpmd コマンドを使用します。

0:004> !sos.bpmd exceptiontest1.exe ExceptionTest1.Form1.button1_Click
Found 1 methods...
MethodDesc = 003859d8
Adding pending breakpoints...

処理を流します。

0:004> g
(133c.1768): CLR notification exception - code e0444143 (first chance)
JITTED ExceptionTest1!ExceptionTest1.Form1
.button1_Click(System.Object, System.EventArgs)
Setting breakpoint: bp 00420328 [ExceptionTest1.Form1.button1_Click(System.Object, 
System.EventArgs)]
Breakpoint 0 hit
eax=003859d8 ebx=01cd0b54 ecx=01cb3a5c edx=01cb7aec esi=01cb8cc4 edi=01cb7aec
eip=00420328 esp=0024e974 ebp=0024e98c iopl=0         nv up ei ng nz ac po cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000293
00420328 55              push    ebp

すると上記のように、JIT コンパイルが発生したタイミングで適切なアドレス (ここでは 00420328) にブレークポイントが設定されたことがわかります。 さらに、ブレークポイントがヒットしてブレークしました。

マネージドスタックをみると次のように、確かに button1_Click にいます。

0:000> !sos.clrstack
OS Thread Id: 0x1768 (0)
ESP       EIP
0024e974 00420328 ExceptionTest1.Form1.button1_Click(System.Object, System.EventArgs)
0024e97c 64404170 System.Windows.Forms.Control.OnClick(System.EventArgs)
0024e994 643ff55a System.Windows.Forms.Button.OnClick(System.EventArgs)
0024e9a4 64996da4 System.Windows.Forms.Button.OnMouseUp(System.Windows.Forms.MouseEventArgs)
0024e9c0 649675d3 System.Windows.Forms.Control.WmMouseUp(System.Windows.Forms.Message ByRef, 
System.Windows.Forms.MouseButtons, Int32)
0024ea4c 64c99b66 System.Windows.Forms.Control.WndProc(System.Windows.Forms.Message ByRef)
0024ea50 64c98325 [InlinedCallFrame: 0024ea50]
0024eae8 64432550 System.Windows.Forms.Button.WndProc(System.Windows.Forms.Message ByRef)
0024eaf4 64438640 System.Windows.Forms.Control+ControlNativeWindow.OnMessage(System.Windows
.Forms.Message ByRef)
0024eafc 644385c1 System.Windows.Forms.Control+ControlNativeWindow.WndProc(System.Windows.
Forms.Message ByRef)
0024eb10 6443849a System.Windows.Forms.NativeWindow.Callback(IntPtr, Int32, IntPtr, IntPtr)
0024ecb8 002709dc [NDirectMethodFrameStandalone: 0024ecb8] System.Windows.Forms
.UnsafeNativeMethods.DispatchMessageW(MSG ByRef)
0024ecc8 64448cce System.Windows.Forms.Application+ComponentManager.System.Windows.Forms
.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32, Int32, Int32)
0024ed64 64448937 System.Windows.Forms.Application+ThreadContext.RunMessageLoopInner(Int32, 
System.Windows.Forms.ApplicationContext)
0024edb8 64448781 System.Windows.Forms.Application+ThreadContext.RunMessageLoop(Int32, 
System.Windows.Forms.ApplicationContext)
0024ede8 64405911 System.Windows.Forms.Application.Run(System.Windows.Forms.Form)
0024edfc 0042009a ExceptionTest1.Program.Main()
0024f028 71401b4c [GCFrame: 0024f028]

これでブレークできたので、目的は達成です。

おまけ JIT コンパイルの様子をみる

さて、JIT コンパイルの状態について少しだけみてみましょう。続きを読む

ここまでお読みいただき、誠にありがとうございます。SNS 等でこの記事をシェアしていただけますと、大変励みになります。どうぞよろしくお願いします。

© 2024 Web/DB プログラミング徹底解説