This walkthrough will guide you through how to use Debug Assistant to trace a program execution. You should see all the
details in getting trace result. You may also want to see a video demo from here
Download Sample Project "SimpleTest"
SimpleTest.zip
Here we use a sample VC++ MFC project
to demonstrate how the Debug Assist is normally used
step by step. The project name
is "SimpleTest", it is a VS 2005 project, if you are using VS 2008, you may convert
it to 2008 project. Please download SimpleTest project from the above link before continue. SimpleTest is almost a barebone MFC
project. Most of the code is generated by the IDE. Files that are our concern are
SimpleTest.cpp, which is the main application initialization code, and SimpleTestDlg.cpp,
the main dialog implementation. A few functions are added at the bottom of this
file in addition to the MFC generated code. Only function need to mention is CSimpleTestDlg::OnCtlColor() which is the message handler of WM_CTLCOLOR.
This is to demonstrate the situation where you may see too much trace result to
find the useful part.
Walkthrough 1. Basic Trace
1) Setup Trace Scope
Make sure debug assistant window is
visible.
Build all projects in the solution. There is only one project in this case. Before
build, check your project settings: C/C++->General->Debug
information format, make sure "Disabled" is not selected. It is a good idea to switch
your project to Debug build.
Click Setup Trace Scope to bring up Setup Trace Scope dialog. In Select modules for trace, check file
SimpleTest.cpp, SimpleTestDlg.cpp.
Select SimpleTest (module) node (corresponding to project SimpleTest), module file
location became editable. Leave the default: $(ProjectOutputFile),
because that's where the module file (SimpleTest.exe) is located. This
cell can not be blank. In "Trace all functions except" section, leave it blank,
since at the moment, we have no idea which function will be hit. We trace all functions.
However, at the bottom of this section, there is Default Exceptions button, click
this button shows all functions that will be excluded in trace. Those functions
generally are not user's interest but can generate too many execution points. You
may uncheck some functions in this list for them to be traced. This is usually undesirable.
At the bottom of this dialog, Startup program is the full path of the startup program
and its command line arguments if there is any. Startup program has to be a valid
executable. It can not be blank. You may click Browse button to find the executable.
For our case it is "C:\VSIP\Test Projects\SimpleTest\debug\SimpleTest.exe".
Click OK button. That's all about setting up trace scope.
2) Start Process
Now it is time to startup the program for trace. Before that, click Turn On Trace
button to switch trace on. Reason we turn trace on before start the program
is we want to record the startup up stage as well.
Click Start Process to start program, then select Trace function only, because we
don't know at the moment how large the trace result will be, it can be really big
if trace every line. (for our SimpleTest project, it won't be large, but we want
to demonstrate the normal tracing process.)
During the program startup process, you will see progress bar showing code loading
process, then Visual Studio status bar will show instrumentation process, program
is start and hooked up. For this test case, these all goes very fast. Depending
on the size of your code and the scope you have selected. The process startup may
take a few seconds. In extreme cases, it can take minutes.
You can click Show Trace Message to check if there is anything wrong during the
trace.
3) Run Program and Record Result
Run Program. Remember the program is under trace. All activities happening in our
selected code will be recorded. Now in SimpleTest program, click button Change
Text. We shouldn't feel any noticeable slow down during the run of SimpleTest. Now,
go to Debug Assistant window, click Turn Off Trace to stop recording. You may turn
on trace later for further trace, but be aware there is gap in timing during the
time the trace is off. So, the trace is stopped.
4) Analyze Result
Click Show Trace result to show result. The graphic part shows two function nodes
in the root node (dash-lined rectangle). That says two functions are called on the
highest level of the call hierarchy within our trace scope. Move mouse cursor over
the two function nodes to see what they are. The message line on the top shows:
call -> CSimpleTestApp::CSimpleTestApp, meaning this
is the lines that calls function CSimpleTestApp::CSimpleTestAp();
call -> CSimpleTestApp::InitInstance, meaning this is where CSimpleTestApp::InitInstance()
is called.
CSimpleTestApp::InitInstance is of our interest. You may notice in this test project,
all of the program execution except for the constructor of class CSimpleTestApp
are contained in this function. Execution finished when this function returns. This
is true at least from a programmer's point of view. So, most of the function calls
are hidden in side of this function. Click this function node, it is then extended
to the next line.
There are about 40 function nodes inside of CSimpleTestApp::InitInstance() as showed
in the picture. Right click on CSimpleTestApp::InitInstance(), then click Functions
calls. It shows there are actually 4 different functions called by CSimpleTestApp::InitInstance(),
they are:
CSimpleTestDlg::CSimpleTestDlg(),
CSimpleTestDlg::OnInitDialog(),
CSimpleTestDlg::OnBnClickedChangeword(),
CSimpleTestDlg::OnCtlColor().
The first three each is called once, last function is called more than 30 times.
In our case, we have no interest in last function. In real cases, things can go
extreme, there can be hundreds of calls of some functions which we have no interest
of, but it make a few interesting ones hard to find. Here is what we do to the make
it easy:
5) Refine Trace Scope
First click Terminate Process button to stop current process. Current trace result
will be replaced when we start the process again. Click Setup Trace Scope to bring
up Setup Trace Scope dialog. Uncheck SimpleTest.cpp to exclude this file, because
there is nothing we want to check in this file. Then select file SimpleTestDlg.cpp,
at the right, in Trace all functions except, uncheck Inherit from parent, then add
following text to the textbox:
CSimpleTestDlg::CSimpleTestDlg, CSimpleTestDlg::OnCtlColor
6) Trace Again
Now start process, choose trace every line, because we are quite sure there is not
going to be a lot of trace point hit in our trace. Then turn on trace. Note here
we turn on trace after program started, because it seems from last trace result
there was not much we want to see in the program start up phase. From SimpleTest
program, click Change Text button. Then go to Debug Assistant window, turn off trace.
Click Show Trace Result to bring up result view.
7) Examine Result
This time, we see one node only on the root:
CSimpleTestDlg::OnBnClickedChangeword
This is the one we want to see. Expend this node, among other nodes, there is a
function node: CSimpleTestDlg::SwapLetters, from its color (red) you know this node
takes more than 50% of time in function CSimpleTestDlg::OnBnClickedChangeword. Put
cursor on it you will see it actually take 86.9% of its parent's time. Again, expend
this function, and click on the expended function. You can see that there is slider
showing at left side of the line. Put cursor on the slider, you will see there is
a
arrow button on it. Drag and move the head of the slider, current line moves accordingly
in the IDE code window, if the file is not open, it will open the code window first.
Click the arrow button to play the result automatically. You can also check a special
way to show loops. It is very compact no matter how long the loop is, but it still
let you check execution of each loop. Please note, the way a loop is wrapped up
is: only first N-1 loops are wrapped up in one node, the last loop is not.
Now we have got what we want to see. You can explore the execution flow freely.
Debug Assistant provides you the best way to see it.
There are save/open buttons that let you save results and view them later.
Walkthrough 2. Attach Process
There are cases when you want to trace a process that is
already started. Assume Setup Trace Scope is already done in walkthrough 1. Now
run program SimpleTest.exe outside of Visual Studio IDE, then go to Debug Assistant
window, click Attach Process button. Click Refresh button, SimpleTest should appear
on the list. Select and attach it, choose Trace every line. Now program SimpleTest.exe
is hooked up with Debug Assistant. Click Turn On Trace. Now your execution is recorded
until you turn trace off.
Walkthrough 3. Trace Specific Functions Only
Sometimes we know exactly which function(s) we want to
check. To make trace more efficient, we can setup trace some functions only. In
Setup Trace Scope dialog, select file SimpleTest.cpp, uncheck Inherit from parent,
then put the following text in the textbox:
{CSimpleTestDlg::OnBnClickedChangeword, CSimpleTestDlg::SwapLetters, GetSentence}
This tells Debug Assistant that we want to record these functions only, everything
else is ignored. Start program as we did in Walkthrough 1, you should get the same
result.
Walkthrough 4. Trace Multiple Threads
Here we are going to show an important feature: show thread relationship.
This gives you how threads overlap in terms of time order. In the case of SimpleTest,
startup program and start trace. Make sure file SimpleTest.cpp is checked and no function
exceptions. Now in SimpleTest program, click Test Threads. Now show trace results.
There are three threads showing in the result view. Top one is the main thread,
the bottom two threads are created after the button click. Put mouse cursor over
first node of the second thread, then right click, click Check thread relation.
It draws a line between the first thread and the second thread. This tells you when
was the second thread started. You can hide the line by click the Hide Relation
Chart.
|
Voice from our clients
"If you have a large project, programmer spend a lot of time figuring out what is
going on in the code. That's where Debug Assistant can help. It's a great tool.”
|