Previous debugger series entries: I, II, III, IV, V
This week's installment of the debugging NetCF applicaitons using CorDbg series covers function evaluation (funceval).
Commands referencedf[unceval] Function evaluationnewo[bj] Create a new object via function evaluationnews[tr] Create a new string via function evaluationsh[ow] Display source code linesw[here] Display a stack trace for the current thread
Modes referencedShowTypeArgs Type arguments to generic methods will not be shown in stack traceShowModules Module names will not be shown in stack trace
For those who aren't familiar with it, function evaluation allows you to experiment with method calls while debugging. Typically, this doesn't impact the running of your application. I say "typically" because if the method you call during a funceval changes class/application global/instance data, the running of your application can be altered.
Static methodsEvaluating static methods is, by far, the easiest form of function evaluation. All you need to do is call the method with your desired arguments. The funceval, shown below, takes two arguments (both integers) and reports back which is largest.
(cordbg) f NetCF.Test.TestDebuggee::PrivateStaticMethod 55 34Function evaluation complete.$result=(strong handle, Size: 4) (0x0004c78c) "arg1"
The only part that may get tricky is getting CorDbg to find the function... If you have been reading the previous parts of this series, you may remember that I recommend keeping the your debugger modes set as shown below.ShowArgs=1ShowModules=1
ShowModules and ShowArgs are really quite helpful here. If you are having a hard time getting CorDbg to evaluate your method, use the stack to help you.
My first attempt at producing the above example hit a snag:(cordbg) f TestDebuggee::PrivateStaticMethod 54 33Could not find function: TestDebuggee::PrivateStaticMethod
Since I had ShowModules enabled, I was able to see the fully qualifies class name and successfully evaluate the method:(cordbg) wThread 0x716f537a Current State:Normal0)* NetCF.Test.TestDebuggee::Main +0000[IL] in <path>\TestDebuggee.cs:32
Instance methodsEvaluating instance methods is a little trickier, but not by much. If you have ever done COM programming in C, this will seem natural to you. Function evaluation on instance methods require an additional argument to the call. You need to provide the debugger with the object from which you want to invoke the method (pran is the variable that contains the object instance).
(cordbg) f SomeOtherNamespace.PrivateClassInAnotherNamespace::ReturnMagicNumber pran 45Function evaluation complete.$result=1169951822
Of course, since you must have an instance of an object to pass. There are two ways to get an instance of your target object... First, you can execute enough of your application for the object to have been created (as shown above) -- watch out for methods that update object instance state.
The second option (the one I personally like best) is to have the debugger instantiate an instance of your target object on your behalf.(cordbg) newo SomeOtherNamespace.InternalClassInAnotherNamespaceFunction evaluation complete.$result=(strong handle, Size: 4) (0x0010058c) <SomeOtherNamespace.InternalClassInAnotherNamespace>
Once complete, $result will contain an instance of your target object. You can then evaluate your target method, without need to run more of your application than you wish to and without fear of tampering with the state of your applications instance of the object.
(cordbg) f SomeOtherNamespace.InternalClassInAnotherNamespace::ReturnMagicNumber $result 6Function evaluation complete.$result=3
You'll notice that $result gets overwritten whenever a function evaluation occurs. If you write down the hex value displayed when the newo[bj] command returns (0x0010058c, in my example), you can use that in future f[unceval] calls.
(cordbg) f SomeOtherNamespace.InternalClassInAnotherNamespace::ReturnMagicNumber 0x0010058c 12Function evaluation complete.$result=0
(cordbg) f SomeOtherNamespace.InternalClassInAnotherNamespace::ReturnMagicNumber 0x0010058c 14Function evaluation complete.$result=2
One other note, funceval can only accept variables, addresses and integers as arguments. If you need to pass a string to a method, you will need to use the new[str] command (also places the object instance in $result). You can then call methods which take strings.(cordbg) newstr SomeoneFunction evaluation complete.$result=(strong handle, Size: 4) (0x0010043c) "Someone"(cordbg) f NetCF.Test.TestDebuggee::PublicInstanceMethod app $result 75Function evaluation complete.$result=(strong handle, Size: 4) (0x00100a94) "Hey, everyone! Someone is 75 years old!"
Pretty neat, isn't it? Well, that's all for today,-- DK
Disclaimers:This posting is provided "AS IS" with no warranties, and confers no rights.Some of the information contained within this post may be in relation to beta software. Any and all details are subject to change.
[2004-07-23: Edited to clarify newstr example]