Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
72 views

Debugging With Visual Studio 2010

Discover how to debug source code using Visual Studio. There are also notes on how to debug release code using WinDBG, ADPlus etc.

Uploaded by

mahendrent
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
72 views

Debugging With Visual Studio 2010

Discover how to debug source code using Visual Studio. There are also notes on how to debug release code using WinDBG, ADPlus etc.

Uploaded by

mahendrent
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 10

Debugging

Overview
To start debugging an application, you have a few options:

Open the project with the source code in Visual Studio, select the Debug
configuration, press Play to start debugging.
Open the project with the source code in Visual Studio, launch the application
externally, then attach to it from Visual Studio
Launch the application externally, then attach to it from Visual Studio. In this case if
you have the source code, an exception may load it correctly. However, this method is
useful if you just need to know the details of the exception being raised, or the list of
modules loaded, inspect memory, pause the code etc.
Use gflags to tell Windows to use a debugger whenever the application launches e.g.
use the vsjitdebugger.exe, which allows you to launch or select an instance of Visual
Studio to attach to the application. This method is particularly useful when debugging
services since you can't start a service from inside Visual Studio.
Use the CDB debugger, or WinDBG to debug your code, or to analyse memory
dumps.

Basic debugging in Visual Studio


Run Visual Studio as Administrator.
Load all the code you wish to debug into the Solution e.g. both the Static Library and Control
Module projects or the a .Net project. Visual Studio has the concept of a startup project. This
is the one that will be launched when you start debugging. Right click on a project in the
solution explorer to change the startup project. If you are debugging an exe, you may select
the platform and configuration type - ensure debug is selected. For dll's you must configure
which exe will launch when debugging starts. Edit this in the project settings.
It is best to have the symbol files (pdb) which match the code, rebuild the project if youre
unsure. If you notice the yellow context cursor jumping to places where it shouldnt, or break
points with ?, your symbol files and source code are probably out of sync.
Select suitable locations for breakpoints (press F9 to add a breakpoint).
Press Play (or F5) to start debugging. The application will start and the debugger will stop at
your breakpoint.
You may also attach to an application that is already running. Select Tools/Attach in the
menu and select the executable you wish to attach to. In most cases Visual Studio
automatically determines the type of the application and attaches appropriately. However, in
certain cases you may want to change this behaviour. Select native, managed or mixed before
clicking ok on the attach window.

Breakpoints
Press F9 to add a breakpoint at the current line in your code. Press F9 again to remove the
breakpoint (toggle).
When you run your code, the debugger will break at that line before it is executed.

The choice of location for a breakpoint requires some consideration. If you break too early,
you will need to step over many lines of code, but if you break too late, you may miss a
critical event in your code.
You can also press the Pause button in Visual Studio at any point to stop the execution of
code and break at the current line. However, your user code may not be executing at the time,
or the current line may show a different thread than expected.

Context
When your code stops at a breakpoint, the context cursor, a yellow cursor in the code margin
indicates the line of code to be executed next.
If you press F10 or click the Step Over option on the Toolbar in Visual Studio, the current
line of code is executed and the context moves to the next line.
A few shortcuts can help you execute your code

continue (F5)
Continues execution of your code until the next breakpoint is hit.
step over (F10)
Execute the current line, and move the context to the next line.
run to cursor (Ctrl+F10)
If your cursor (edit cursor in the code) is a few lines below, code is executed and stops
at your cursor.
step into (F11)
If the context is at a line of code that is a function/property or some other compound
code, then the context moves into the function/property i.e. the code you see is
changed to the function/property
step out (Shift+F11)
Executes all of the code in the current function/property and returns the context to the
calling function.
step into specific (native C++ only)
Same as F11 but allows you to select which function you would like to step into
set next statement (Ctrl+Shift+F10)
Allows you to skip code. Place your cursor on a line of code and press Ctrl+Shift+F10
to skip other lines and move the context to the line selected.
You may find it easier to drag the context cursor to the line you wish to execute next.
most of these options also apply to the disassembly window

Data Tooltips
As you are executing lines of code, the values of variables will change. To view the current
value of a variable hover over it with your mouse.
A data tooltip shows the current value. For some variable types, a data visualization window
appears allowing you to view the value easier e.g. if you hover over a DataTable, you can
view each cell in a table format.
Most data tooltips also allow you to change the value of the variable. Click on the tooltip and
type in a new value.

Watch window

Use the watch windows when data tooltips become too tedious, or when you want to view the
same variables continuously.

To add a variable to a watch window


o Dragging the variable from the source code
o right click on the variable in the source code and select, add to watch
o In a new line in the watch window, type in the name of the variable (intellisense)
Up to 4 watch windows so you can look at many variables at the same time
Use the watch window to
o set values
type in the new value in the appropriate column
o call functions
these get called once only, but you can force an update but clicking the refresh
button next to the function
Too many variables, or variable with large tree structure slows debugging

In C++ you have a few more options:

memory, m
e.g. 0x24BC, m cd represents global memory that has not been initialised. cc shows
un-initialised local memory. dd is free memory while fd is memory that you cannot
access.
pointer, size
e.g. pArr, 10
&MyVar
returns the memory address of the variable
@Err
Calls getlasterror and shows the result
Registers
e.g. EAX
Formatters
e.g. d (format as signed decimal), c (char), s (string)
e.g. MyVar,d
Uninitialised global shown with value 0xCDCDCDCD
Uninitialised locals shown with value 0xCCCCCCCC
Freed memory shown with value 0xDDDDDDDD
Memory out of the process/inaccessible shown with value 0xFDFDFDFD

Output Window

Toggle between Debug/Build and Source Control windows.


Build Window shows build errors etc.
sometimes more useful than the Task Window since the order and detail are more
apparent.
Debug Window shows Traces/exceptions etc.
use TRACE or System.Debug.Write in your code
Source Control Window shows check ins/check out

Exceptions

Break into debugger when


(used to catch unhandled 1st and 2nd chance exceptions.)
Usually you press Ctrl+Alt+E, the check the Exception types you want the debugger
to break on. This is before the exception is caught by your code.
Very useful when you forgot to put in your own catch statements, or when you dont
know where the exception is being thrown or what the exception is.
You can add custom .Net exceptions by name, and Win32 exceptions by number.
Set the Basic Runtime Checks property for your project to Both (/RTC1) in the Code
Generation page under C/C++
Enable Basic runtime checks in properties window
@err in the watch window will return the last error.
$exception shows the last exception

Advanced debugging in Visual Studio


Stack Window
Use the Call Stack to view the call order of functions (i.e. the nested list of function calls that
brought you to the current context)

Navigating
double click to switch to different frame.
Used with watch window
Shows parameters types and parameter values
Set breakpoints

Command window
Run Visual Studio Commands, similar to when writing a macro e.g.

Edit.Find m_bMyBool
File.Open C:\pagefile.sys

Intellisense for ease of us

Immediate window

? To Evaluate expressions (like the watch window)


Execute statements; assign variables
Print variables
You can switch between the command and immediate window, or type commands in
the immediate window by prefixing with >

Breakpoints
Once a breakpoint has been set, advanced options can be configured. Right clicking a
breakpoint brings up a property window where conditions for the breakpoint can be set.

Hit Count
Useful for long loops
Try setting the condition to a huge number to find when a problem occurs. Then when
the exception etc. is encountered, take a look at the hit count for the breakpoint. Now
you know when to break
Testing a variable
You may also check the value of a variable and break when it matches a condition
Data Breakpoints
In C++ data breakpoints allow you to break whenever a variable/memory location is
modified.
Memory Allocation Breakpoint
Set a breakpoint in the watch window by adding a variable with the name
_crtBreakAlloc to break whenever memory is allocated
Set the value of the _crtBreakAlloc variable e.g. to 24 to break on the 24th allocation
use {,,msvcr71d.dll}_crtBreakAlloc when using multithreaded dll version of CRT
(which is the default option for new projects)
Can also be done in code _crtBreakAlloc = 24

Lastly, while breakpoints are useful, too many breakpoints slows debugging. Use the
Breakpoints window to selectively enable/disable breakpoints. This window is also useful for
navigation, if you quickly want to jump around your code to known breakpoints.

Memory Window

Find which location a pointer is referencing, or the memory location of a variable and
type that into the address textbox.
Format as Ansi/Unicode string
Can also view the data as various integral or double types

Disassembly Window

Shows the assembly associated with your source code.


You can do most of the operation as in the source window e.g. set break points, hover
to view values etc.
Shows injected code, framework code and code for which there is no source code.
For example if you debug an Windows executable

Modules Window

Check the location of a module


Make sure the correct version is loaded
The module load address is quite important e.g. when you need to decipher which
export function was called, and all you have is an address to the function

Threads

Switch contexts
Switch context to a different thread by double clicking on it. Then when you press
F10, this thread will execute.
Freeze/thaw threads
When multiple threads are running, the execution context may jump between threads.
Freeze the thread temporarily to prevent its execution.
Set breakpoint per named thread

Task Window
The Task window can be used to show custom tasks by right clicking on the pane and
selecting Show All from the pop-up menu.
Comments specifically starting with // TODO: will then be listed. Use //TODO: //HACK:
//UNDONE: or custom tags
The options tab can also be used to add your own custom tasks.
The task window only shows tasks for the current project unless it is a bookmark task (added
from the Edit menu)

gflags
Global Flags configures registry entries that tell Windows to treat applications differently.
For example, you can tell windows to enable heap checking for your application.

Installation and configuration


Install Debugging Tools for Windows which is part of the Windows SDK.
The latest one is for Windows 7 S:\Development\Microsoft Windows Platform
SDK\Windows 7 SDK

Usage

Run Global Flags and then click on the Image tab.


Type in the name of the application e.g. WinClient.exe
Then press the Tab key.

Debugger
You can use Global Flags to configure an alternative debugger for your application.

Check the Debugger box


Type in vsjitdebugger.exe
This is the Visual Studio Just In Time debugger.
Whenever your application starts, a window will appear allowing you to select an
instance of Visual Studio to use to debug the application. Or you can start a new
instance. This is currently the only way to debug the start code in services.
Ensure that UAC is turned off!

Heap checking

If the debugger in step 1 does not detect your problem, you may need to turn on heap
checking which validates heap memory e.g. buffer overruns etc.
In the Debugging Tools for Windows directory run gflags.exe with no arguments.
Since we are interested in a user module ignore the settings for System Registry and
Kernel Mode. Type in dllhost.exe for the Image File Name. Then either select the
Image File Options radio button or Press the Tab key.
gflags sets registry keys for applications that you want Windows to analyze, once they
have been set, they will always be active (even after rebooting) unless you turn them
off.
If youre interested, you can have a look at the registry key:
HKLM\Software\Microsoft\Windows NT\Current Version\Image File Execution
Options\You Application.exe (e.g. dllhost.exe)
Place a check next to the following options for dllhost.exe in gflags.

1.
2.
3.
4.
5.
6.
7.

Enable heap tail checking


Enable heap free checking
Enable heap parameter checking
Enable heap validation on call
Enable application verifier
Enable heap tagging
Enable page heap.
On later version of gflags, Enable application verifier may be on a different Tab.

Once you are done, click apply.


To verify your settings, close gflags and open it again. Type dllhost.exe and hit tab.
Image File Options. You checks will reappear.
Now what have you done?
Well you have told Windows to throw exception when any of the heap checks you
specified have failed. And when the application is running in a debugger as in our
case, we will be notified with a message and a dump file.

CDB Debugger, WinDBG


Sometimes errors occur on production machines with release versions of programs, and no
matter what you try you cannot recreate the error on a debug build. In this case, you would
need to "debug" the release version directly, and you would need to use some debugger other
than Visual Studio.
Symbol files (PDB files in our case) can be generated for release code, just as for debug code.
These must be copied to the machine where the error occurs. The following discusses how to
use ADPlus, a preconfigured script to analyse your program, and then to use WinDBG for
advanced analysis.

Installation
Install the Platform SDK for your version of Windows. The current version is available here:
\\mntksrv006\MAC\Software\Development\Microsoft Windows Platform SDK\Windows 7
SDK The default install will create a new folder C:\Program Files\Debugging Tools for
Windows (x64)

ADPlus
ADPlus can be used to analyse a program that's crashing often, or to analyse a program that
has hung.
The main purpose of ADPlus is to "take a dump" (mind the language). It does this by
attaching a debugger (CDB) to your processes and watching for exceptions or hangs etc.
Set Environment Variables
Right click on My Computer and select Properties.
Go to the Advanced tab and select Environment Variables
Select New under System Variables and set

_NT_SYMBOL_PATH =
SRV*C:\Symbols*http://msdl.microsoft.com/download/
symbols
(where C:\Symbols is the location of a local
folder to cache symbols)
Also add

_NT_EXECUTABLE_IMAGE_PATH =
C:\Windows;C:\Windows\System32;C:\Mintek\StarCS\Se
rver;C:\Mintek\StarCS\Server\Modules;
(or an equivalent location of your dll files)
Run ADPlus in crash mode
Open a command prompt and navigate to the Debugging Tools for Windows folder.
Also open Task Manager and find the PID of the StarCS Slave.exe process (or dllhost.exe for
older versions of StarCS).
Type the following in the command prompt

Adplus crash p [StarCSSlavePID]


Substitute your StarCS Slave PID.
A new command window should now open and display a few messages finally stopping at >
g. Now start StarCS via the StarCS Manager and wait for exception messages in the
command window. A dump file will be created for every exception encountered.
Modify the following .cfg file for more control over ADPlus:

<ADPlus>
<Settings>
<RunMode> CRASH </RunMode>

<OutputDir> c:\MyDumps </OutputDir>


</Settings>
<Exceptions>
<Config>

AllExceptions
<Actions1>Log;MiniDump</Actions1>
<Actions2>Stack;FullDump;Log;EventLog</Actions2>
</Config>
<Config>

av
<Actions1>Log;MiniDump</Actions1>
<Actions2>Stack;FullDump;Log;EventLog</Actions2>
</Config>
</Exceptions>
</ADPlus>
Copy the text into notepad and save as C:\Program Files\Debugging Tools for
Windows\Adplus.cfg.
Then change the command to:

Adplus c Adplus.cfg p [StarCSSlavePID]


Introduction to analysing with WinDBG

In order to properly analyse a dump file, it is necessary to have the correct version of
the dlls and their corresponding pdb (symbol files).
In this case, the dlls that were installed on the PC on which the dump was created
Verify that _NT_EXECUTABLE_IMAGE_PATH and _NT_SYMBOL_PATH point
to locations where the dlls and pdb files respectively reside
Other pdb files that relate to windows dlls may also be required.
Ensure that you have a valid internet connection. WinDBG will use the Symbol server
to download the pdbs are required (hence the url,
http://msdl.microsoft.com/download/symbols NB: you cannot browse to this url, only
a symbol server can download symbols from this location.)
Now type windbg.exe -v -n Q at a command prompt.
The options just specify verbose messages and strict symbol matching
Open your dump file by selecting File\Open Crash Dump. and browsing to your
,dmp file

Select View\Call Stack to show a call stack at the exception.


The top of the stack shows the function call last executive and this is usually a call to
an exception handler to handle the exception. The next function down the window is
the function that called the one above it etc. This should give you an indication as to
which call the function failed at
Symbols files are quite important here in that incorrect functions will be listed in the
stack if you dont have them.
You can have a look at all the modules that were loaded and whether you have the
symbols files or the exports for the dll. Select Debug\Modules. NB: Only the symbols
or exports of necessary modules are loaded. Thus the modules window may show
some modules without symbols or exports.
On the main command window of WinDBG, you can type some commands.
An interesting one is !analyze v that asks for an analysis of the dump file

You might also like