The NGWS SDK Debugger

The Microsoft NGWS SDK debugger is intended as an interim tool for debugging applications written and compiled for the Microsoft NGWS runtime. The NGWS SDK debugger, and the accompanying documentation, is based on work being done for the Microsoft Visual Studio 7.0 debugger. As a result, the documentation refers mostly to the Visual Studio debugger, rather than the NGWS SDK debugger. In most cases, the information is applicable to both debuggers. However, you will find sections of the documentation describing some features that are not implemented in the NGWS SDK debugger (see the next paragraph). You can simply ignore these features and sections.

Here are some of the main differences between the NGWS debugger and the Visual Studio debugger as described in the documentation:

  • The NGWS SDK debugger does not support the debugging of Win32 native code applications. Only applications written and compiled for the Microsoft NGWS runtime can be debugged with the NGWS SDK debugger.
  • Remote debugging is not implemented in the NGWS SDK debugger.
  • The Registers window is implemented in the NGWS SDK debugger, but no register information appears in the window. Other operations that involve registers or pseudoregisters, such as displaying or changing a register value, are not supported.
  • The Disassembly window is implemented in the NGWS SDK debugger but shows the disassembly code that would be generated for the application if it were compiled as Win32 native code rather than NGWS runtime code.

The NGWS SDK Debugger Solution Model

  • The NGWS SDK debugger uses solutions to associate source files and the applications being debugged. A solution is created automatically when you open a compiled application and its associated source file or files. The next time you debug the same application, you can open the solution instead of having to load the source file and the compiled application separately.

To open an application for debugging (the first time)

  1. From the Debug menu, select Program to Debug.
  2. In the Program to Debug dialog box, go to the Program box and click the ellipsis button (…). The Find Program to Debug dialog box appears.
  3. Navigate to the directory containing the EXE you want to debug and select the EXE.
  4. Click Open.

    This takes you back to the Program to Debug dialog box. Notice that the Working directory has been set to the directory containing your EXE.

  5. In the Arguments box, type any arguments that your program requires.
  6. Click OK.
  7. From the File menu, choose Open, then click File.
  8. In the Open File dialog box, choose the source file you want to open.
  9. Click OK.
  10. To open additional source files, repeat steps 8-10.

This process automatically creates a solution for your debugging session. If you select Start or Step, the Save File As dialog box opens so you can save the solution. If you select Exit or Close Solution, a message box appears which prompts you to save the solution first.

To open an existing solution

  • From the File menu, choose Open.

See Also

  • Using the Debugger

© 2000 Microsoft Corporation. All rights reserved.


Using the Debugger

The Visual Studio debugger includes menu items, windows, and dialog boxes. You can obtain help on any window, dialog box, or control by selecting the item and pressing F1. You can use drag-and-drop to move debug information between interface elements.

  • Execution Control
  • Attaching to a Running Program or Multiple Programs
  • Breakpoints
  • Inspecting Your Program
  • Handling Exceptions
  • Edit and Continue
  • Using Expressions in the Debugger

See Also

Debugging Your Program


Execution Control

The Visual Studio debugger provides powerful commands for controlling the execution of your application. Using debugger commands, you can:

  • Start execution
  • Break execution
  • Stop execution
  • Step through your application
  • Run to a desired location
  • Set the execution point

See Also

  • Execution Commands


Starting Execution

To start debugging

  • From the Debug menu, choose Start, Step Into, Step Over, or Run to Cursor.

If you choose Start, your application starts up and runs until it reaches a breakpoint. You can break execution at any time to examine values, modify variables, and otherwise examine the state of your program.

If you choose Step Into or Step Over, your application starts up, executes its first statement, then enters a break state.

If you choose Run to Cursor, your application starts up and runs until it reaches a breakpoint or the cursor location in the source or Disassembly window (whichever comes first).

Your solution may contain more than one project. In that case, you can choose the startup project that will be launched by the Debug menu execution commands. Alternatively, you can start a selected project to start from the Solution Explorer.

See Also

Execution Control


Choosing the Startup Project

The startup project is the project in a Visual Studio solution that starts when you choose an execution command such as Start from the Debug menu.

To choose a startup project

  • In the Solution Explorer window, right-click on a project name and choose Set as StartUp Project from the shortcut menu.

See Also

Starting Execution


Starting Execution Of a Selected Project

To select a project and start execution

  1. In the Solution Explorer window, right-click on the project you want to start.
  2. From the shortcut menu, choose Debug and Step Into.

See Also

Starting Execution


Stopping Execution

Stopping execution means terminating the program you are debugging and ending the debugging session. It should not be confused with breaking execution, which temporarily halts execution of the program you are debugging but leaves the debugging session active.

To stop debugging

  • From the Debug menu, choose Stop Debugging.

If you to stop the run you are currently debugging and immediately begin a new run, you can use the Restart command.

To stop debugging

  • From the Debug menu, choose Restart.

See Also

Execution Control


Breaking Execution

When you are debugging an application with the Visual Studio debugger, your application is either running (executing) or it is in a break state. The debugger breaks execution of the program when execution reaches a breakpoint or when a selected exception occurs. You can break execution manually at any time.

To break execution of your program

  • From the Debug menu, choose Break.

    Your program enters a break state. Execution of the program stops, but the program does not exit and you can resume execution at any time.

    Note If the program cannot be stopped for some reason (for example, the program is executing in kernel mode), the debugger freezes all threads and simulates a break. This is known as a "soft break." If you choose an execution command such as Go or Step after a soft break, the debugger reactivates (thaws) the threads. As a result, you may need to choose the Go or Step command twice for execution to resume. A message box informs you when a soft break has occured.

See Also

Execution Control


Stepping

One of the most common debugging procedures is stepping — executing code one unit (statement, line, or machine instruction) at a time. With the Visual Studio debugger, you can choose the step unit you want to use — a language statement, a source line, or an assembly instruction.

To change the step unit

  • From the Debug menu, choose Step By and select Statement, Line, or Instruction.

The Debug menu provides three commands for stepping through code:

  • Step Into
  • Step Over
  • Step Out

Step Into and Step Over differ in only one respect — the way they handle function calls. Either command instructs the debugger to execute the next unit of code. If the next unit contains a function call, Step Into executes only the call itself, then halts at the first unit of code inside the function. Step Over executes the entire function, then halts at the first unit outside the function. Use Step Into if you want to look inside the function call. Use Step Over if you want to avoid stepping into functions that have already been thoroughly debugging and are probably not the cause of your problem. (For example, Windows APIs.)

On a nested function call, Step Into steps into the most deeply nested function. If you use Step Into on a call like Func1(Func2), the debugger steps into the function Func2. If you want to step into another function within the nest, use Step Into Specific Function command from the shortcut menu.

Use Step Out when you are inside a function call and want to return to the calling function. Step Out resumes execution of your code until the function returns, then breaks at the return point in the calling function.

You cannot access the Step commands if your application is running. You must wait for the program to reach a breakpoint or choose Break from the Debug menu before you can begin stepping.

To step into a program that is not yet executing

  • From the Debug menu, choose Step Into.

To step while debugging

  1. If necessary, choose Break from the Debug menu.
  2. From the Debug menu, choose Step Into, Step Out, or Step Over.

When you are stepping into a nested function call, you can use Stepping into a Specific Function, to choose which function you want to step into.

See Also

Execution Control


Stepping Into a Specific Function

When you are stepping into a nested function call, you can use Step Into Specific Function, located on the shortcut menu, to choose which function you want to step into. For example, on a call to Func1(Func2), you could choose to step into Func1 or Func2. This command works for any number of nesting levels.

In addition, you can use Step Into Specific Function to step into some C++ member functions, such as MemberFn in the following code:

CMyClass::MemberFn();

You cannot use Step Into Specific Function with C++ virtual functions.

To step into a specific function

  1. Advance the execution point to the function call you want to step into. (You might use a breakpoint, Step Into, Step Over, or Run To Cursor.)
  2. Right-click on the source window to open the shortcut menu.
  3. From the shortcut menu, click Step Into Specific Function and choose the function you want from the submenu.

    The debugger executes the function call and breaks at the beginning of the selected function.

See Also

Execution Control


Running to a Specified Location

Sometimes, while debugging, you will want to execute to a certain point in code, then break. If you have a breakpoint set at that location, all you have to do is select Start or Continue from the Debug menu. You don't need to set a breakpoint in all cases, however. The Visual Studio debugger provides specific commands to run—

  • To the cursor location
  • To a specified function


Run to the Cursor Location

You can command the debugger to run your application until it reaches the location where the cursor is set. This location may be in a source window or the Disassembly window. (The cursor means the insertion point you set by clicking in the window with the mouse.)

To run to the cursor in a source window

  1. You must be debugging, and your application must be in a break state.
  2. In a source file, click on a source line to move the cursor to that point.
  3. From the Debug menu, select Run To Cursor.

To run to the cursor in the Disassembly window

  1. You must be debugging, and your application must be in a break state.
  2. If the Disassembly window is not visible, choose Windows from the Debug menu and select Disassembly.
  3. In the Disassembly window, click on a line to move the cursor to that point.
  4. From the Debug menu, select Run To Cursor.


Run to a Specified Function

You can command the debugger to run your application until it reaches a specified function. You can specify the function by name (using the toolbar) or you can by choose it from the call stack.

To run to a specified function

  1. On the standard toolbar, type the function name in the Find box and press ENTER. This moves the cursor to the specified function.
  2. From the Debug menu, select Run To Cursor.

To run to a function on the call stack

  1. You must be debugging, and your application must be in a break state.
  2. Open the Call Stack window, if necessary. (Choose Call Stack from the Debug menu, Windows submenu.)
  3. In the Call Stack window, click on a function name to select it.
  4. From the Debug menu, choose Run To Cursor.

See Also

Execution Control


Setting the Execution Point

In the Visual Studio debugger, you can move the execution point to set the next statement of code (or assembly-language instruction) to be executed. An arrowhead in the margin of a source or Disassembly window marks the current location of the execution point. By moving the execution point, you can skip over a portion of code or return to a line previously executed. This can be useful in some situations — for example, if you want to skip a section of code that contains a known bug and continue debugging other sections.

Caution Changing the execution point causes the program counter to jump directly to the new location. Use this command with caution. Please be aware:
  • Instructions between the old and new execution points are not executed.
  • If you move the execution point backwards, intervening instructions are not undone.
  • If you move the execution point to another function, call-stack corruption usually results in a run-time error or exception. If you try this, a dialog box warns you that the operation will move the execution point (current location) to a new scope. The dialog box gives you a chance to cancel the operation.

You cannot set the execution point while your application is actively running. To set the next statement, your application must be in a break state.

To set the next statement to execute

  1. In a source window or Disassembly window, click to select the statement or assembly-language instruction you want to execute next.
  2. From the Debug menu, choose Set Next Statement.

If the statement you want to set is in the same source file or Disassembly window as the current execution point, you can set the execution point by dragging the marker that appears in the left margin of the window:

To set the next statement to execute (in the same source file or Disassembly window)

  • In a source window or Disassembly window, click the execution point marker (yellow arrowhead) and drag it to the location where you want to set the next statement or instruction.

See Also

Execution Control


Attaching To a Running Program or Multiple Programs

With the Visual Studio debugger has the ability to attach to a program that is already running outside of Visual Studio. You can use this attach capability:

  • To debug a program that was not created in Visual Studio.
  • To debug multiple programs simultaneously.
  • To debug a program a running on a remote machine.
  • To start the Visual Studio debugger automatically when a program crashes while running outside of Visual Studio (just-in-time debugging).

Once you have attached to a program, you can use debugger execution commands, inspect the program state, and so on. You ability to inspect the program may be limited, of course, depending on whether the program was built with debug information and whether you have access to the program's source code.

To attach to a running program

  1. From the Debug menu, choose Programs.
  2. In the Programs dialog box, find the program you want to attach to from the Available Processes list. If the program you want to debug is running on another machine, you must first select the remote machine.
  3. Click the Attach button.
  4. In the Attach to Process dialog box, make sure the appropriate program type (for example, Win32 or NGWS runtime) is selected in Choose program types to be attached now and in the future.
  5. Click OK.
  6. At the bottom of the Programs dialog box is a dropdown list labeled When debugging is stopped. Choose the behavior you want to occur when you stop debugging the selected program. In most cases, it is okay to terminate the program when debugging stops, but you may want to keep it running (for example, so that you can attach to it again in the future.) If you attach to a system process, be especially careful. Terminating a system process can have sudden and undesirable effects, including crashing the system. If you don't want the program to terminate when the debugging session ends, choose Detach from this process rather than Terminate this process.
  7. Click OK.

The Available processes list is displayed automatically when you open the Programs dialog box. Processes can start and stop in the background while the dialog box is open, however, so the contents may not always be current. You can refresh the list at any time to see the current list of processes.

To refresh the Programs list

  • Click on the Refresh button.

You can be attached to multiple programs when you are debugging, but only one program is active in the debugger at any given time. You can set the active program in the Programs dialog box.

All Debug menu execution commands affect the active program. If you choose Break from the Debug menu, the debugger breaks the active program. You can break any debugged program, active or inactive, from the Programs dialog box.

To break a debugged program

  1. In the Programs dialog box, locate the process you want to break to in the Debugged Programs list.
  2. Click the Break button.

When are finished debugging an attached program, you can detach from the program.

See Also

Using the Debugger


Setting an Active Program

To set an active program

  1. In the Programs dialog box, locate the program you want to make active in the Debugged Processes list.
  2. Right-click on the program and choose Set as Active Project from the shortcut menu.

See Also

Attaching to a Running Program or Multiple Programs |


Detaching Programs

To detach from a process

  1. In the Programs dialog box, locate the process you want to attach to in the Debugged Programs list.
  2. Click the Detach button.

To detach from all processes simultaneously

  • From the Debug menu, choose Detach All.

If you detach all processes, the debugger session ends automatically.

CAUTION Detaching from a program does not terminate the program. The program continues running on its host machine even though it is no longer attached to the debugger. To make sure the active program terminates, use the Stop Debugging command from the Debug menu. Be careful about stopping system processes, however, which can have sudden, adverse results, including system crashes.

See Also

Attaching to a Running Program or Multiple Programs


Selecting a Remote Machine

To select a remote machine

  1. In the Programs dialog box, select the machine you want to connect to from the Machine list. If you do not find the machine you want on the list:
    1. Check the Transport box and make sure you have the proper transport selected.
    2. Click the ... button next to the Machine list.
    3. In the Browse for Computer dialog box, use the tree control to locate the computer you want on the selected transport.
    4. Click OK.
    5. The computer you selected in the Browse for Computer dialog box should now appear in the Machine list. Makes sure it is selected.
    6. Click OK.

See Also

Attaching to a Running Program or Multiple Programs


Just-In-Time Debugging and Crash Dumps

Just-in-time debugging is a technique for debugging a program that is started outside of Visual Studio. If you have enabled Just-in-time debugging, you can run a program created in Visual Studio outside of the Visual Studio environment. The program will run as normal until an error occurs. At that point, it will launch Visual Studio for debugging.

To enable Just-In-Time debugging

  1. From the Tools menu, select Options.
  2. In the Options dialog box, select the Debugging folder.
  3. In the Debugging folder, select the General Category.
  4. In the Just-In-Time Debugging/Attach group, select Just-In-Time Debugger.
  5. Optional: If you want to enable Just-in-time debugging for certain types of programs only, click on the On This Machine button.
    1. In the Debugger Properties dialog box, in the Program Types box, select the program type you want to enable or disable Just-in-time debugging for (NGWS runtime or Win32 applications, for example).
    2. Select or clear the Allow JIT debugging by this debugger check box.
    3. Click OK.
  6. If you have another debugger installed, select Default Just-In-Time debugger. This will prevent the other debugger from taking control when the crash occurs.
  7. Click OK.

When you are using the Visual Studio debugger, you can save a crash dump file for debugging at a later time. You can debug a crash dump file on another machine or even send it to another developer as an email attachment. You can save a crash dump at any time, but this feature can be especially useful in conjunction with Just-in-time debugging. When a crash occurs and Just-in-time debugging launches Visual Studio, you have the option of saving a crash dump instead of debugging the file immediately. This can be useful if you are testing the program on a machine that does not have source files installed. When the crash occurs, you can save a crash dump file and debug it later on the machine that has the source files.

To save a crash dump file

  • From the Debug menu, choose Save As CrashDump.

To open a crash dump file

  1. From the File menu, choose Open and click File.
  2. In the Open File dialog box, locate and select the crash dump file. (It will have a .dmp extension.)
  3. Click OK.

See Also

Using the Debugger


Speeding Up Remote Debugging

When you debug a program on a remote machine, performance may appear more sluggish than usual. To improve performance, close any debugger windows you are not using. This minimizes the amount of information that must be sent across the connection. Also, minimize the use of data breakpoints on the remote machine.

See Also

Attaching to a Running Program or Multiple Programs


Installing the Remote Debug Monitor

For remote debugging, you must install the Remote Debug Monitor on the remote machine. The Remote Debug Monitor is a small program that communicates with the debugger host and controls the execution of the program you are debugging.

To install the Remote Debug Monitor

  • Run the Visual Studio Setup CD-ROM on the remote machine and choose the appropriate options in the setup wizard.

The Remote Debug Monitor installs the following files during setup.

File | Windows 95 | Windows 98 | Windows NT 4 | Windows 2000
msvcmon.exe | X | X | X | X
natdbgdm.dll | X | X | X | X
natdbgtlnet.dll | X | X | X | X
msdis110.dll | X | X | X | X
msvcp60.dll | X | X | X | X
msvcrt.dll | X | X | X | X
psapi.dll |  |  | X | X
msdbg2.dll | X | X | X | X
mdm.dll | X | X | X | X
cpde.dll | X | X | X | X
pdm.dll | X | X | X | X
metade.dll | X | X | X | X
shmetapdb.dll | X | X | X | X
msvb7.dll | X | X | X | X
C++/C# EE (filename TBD) | X | X | X | X
PDB symbol handler (filename TBD) | X | X | X | X

On Windows NT Windows 2000, the Remote Debug Monitor runs as a service. On Windows 95 and Windows 98, it runs as an application that you can launch from the Start menu.

Note The following message might appear when you try debugging a remote machine:
The VC++ Debug Monitor is not correctly installed and running on machine "remotemachine".
This message means that the debugger did not find the debug monitor running on the remote machine. Start the debug monitor on the remote machine before beginning the debug process.
Note Another message you might receive when you try debugging a remote machine is:
Cannot open file "G:\<filename>" on remote machine.
Verify the filename and check to be sure the file path is correct on the remote target machine.

See Also

Attaching to a Running Program or Multiple Programs


Breakpoints

A breakpoint tells the debugger that an application should break (pause execution) at a certain point or when a certain condition occurs. When a break occurs, your program is said to be in a break state.

The Visual Studio debugger has four types of breakpoints:

  • A function breakpoint causes the program to break when execution reaches a specified location within a specified function.
  • A file breakpoint causes the program to break when execution reaches a specified location within a specified file.
  • An address breakpoint causes the program to break when execution reaches a specified memory address.
  • A data breakpoint causes the program to break when the value of a variable changes.

To provide greater power and flexibility, you can modify the behavior of a breakpoint by adding these properties:

  • A Hit Count property, which determines how many times a breakpoint must be hit before execution breaks. (By default, execution breaks every time a breakpoint is hit.)
  • A Condition, which is an expression that determines whether the breakpoint is hit or skipped.

The Breakpoints window lists all breakpoints currently set in your program and displays their properties. In the Breakpoints window, you can set (create) new breakpoints, delete breakpoints, enable or disable breakpoints, edit a breakpoint's properties, or find the source or disassembly code corresponding to a breakpoint.

The source and Disassembly windows display symbols for function, file, and address breakpoints. These symbols appear in the left margin of the window. A breakpoint that is set and enabled appears as a solid red disk. A breakpoint that is disabled appears as an empty red circle. A breakpoint that is currently unavailable to the debugger (such as a breakpoint in a DLL that is not loaded) appears as a solid gray dot. You can set, enable, disable, edit, or delete these breakpoints in the source or Disassembly window. For details, see Breakpoint Operations In A Source Window or Breakpoint Operations In The Disassembly Window.

No matter which window you are using, you can insert a new breakpoint of any type from the Debug menu.

You can remove all breakpoints from the Debug menu.


Hit Count

The hit count is the number of times a breakpoint is hit. For a location breakpoint, this is the number of times execution reaches the specified location. For a data breakpoint, it is the number of times the value of the variable changes.

The Hit Count property determines how many hits occur before execution breaks.

By default, execution breaks every time a breakpoint is hit. If you specify a Hit Count property, you can choose to:

  • Break always (the default).
  • Break when the hit count equals a specified value.
  • Break when the hit count equals a multiple of a specified value.
  • Break when the hit count is greater or equal to a specified value.

You can specify a hit count for any type of breakpoint — function, file, address, or data.

To specify or edit the Hit Count property, you must Open the Hit Count Dialog Box.

If you specify a Hit Count property for a breakpoint, you can open the Hit Count dialog box to view the current hit count at any time while your program is running.

Tip The debugger does not keep track of the current hit count if the default mode (break always) is selected. If you want to break every time the breakpoint is hit, but you also want to keep track of the hit count in the dialog box, you must choose break when the hit count is a multiple of 1.

See Also

Breakpoints | Breakpoint Hit Count Dialog Box


Opening the Hit Count Dialog Box

To specify or change a hit count when creating a new breakpoint

  • From the New Breakpoint dialog box, click the Hit Count button.

To specify or change a hit count for an existing breakpoint

  1. In the Breakpoints window, select the breakpoint you want.
  2. In the toolbar at the top of the window, select the Properties tool.
  3. In the Breakpoint Properties dialog box, click the Hit Count button.

To specify or change a hit count for an existing breakpoint in a source, Disassembly, or Call Stack window

  1. Right-click on the breakpoint and choose Breakpoint Properties from the shortcut menu.
  2. In the Breakpoint Properties dialog box, click the Hit Count button.

See Also

Hit Count


Condition

A breakpoint condition is an expression that determines whether your program breaks when a breakpoint is hit. The debugger tests the condition each time the breakpoint is a hit. If the condition is satisfied (and the hit count is also correct), the debugger breaks execution. Otherwise, it execution continues.

To specify or change a breakpoint condition, you must open the Breakpoint Condition dialog box.

The condition can be any valid expression recognized by the debugger.

You can specify how the condition is satisfied:

  • When the expression is true (is true in the Breakpoint Condition dialog box), or
  • When the value of the expression changes (has changed in the Breakpoint Condition dialog box)

See Also

Breakpoints | Breakpoint Condition Dialog Box


Opening the Breakpoint Condition Dialog Box

To specify or change a breakpoint condition

— When creating a new breakpoint

  • From the New Breakpoint dialog box, click the Breakpoint Condition button.

— When creating a new breakpoint

  1. In the Breakpoints window, select the breakpoint you want.
  2. In the toolbar at the top of the window, select the Properties tool.
  3. In the New Breakpoint dialog box, click the Breakpoint Condition button.

— When creating a new breakpoint from a source, Disassembly, or Call Stack window

  1. Right-click on the breakpoint and choose Breakpoint Properties from the shortcut menu.
  2. In the Breakpoint Properties dialog box, click the Breakpoint Condition button.

See Also

Condition


Inserting a New Breakpoint From the Debug Menu

No matter which window you are using, you can insert a new breakpoint of any type by selecting New Breakpoint from the Debug menu.

To insert a new breakpoint

  1. From the Debug menu, select New Breakpoint.

    The New Breakpoint dialog box appears.

  2. Select the Function, File, Address, or Data tab, depending on the type of breakpoint you want to set.
  3. Set the properties on the chosen tab.
  4. Select the Condition or Hit Count button, if you want to add either of those properties.
  5. Click OK.

See Also

Breakpoints


Removing All Breakpoints

To remove all breakpoints in your project

  • From the Debug menu, choose Clear All Breakpoints. The breakpoint symbols vanish. So do all breakpoints in the Breakpoints window and everywhere else in your project.

See Also

Breakpoints


Breakpoint Operations In A Source Window

In a source window, you can view, set, enable, disable, delete, or edit a file, function, or address breakpoint. You can insert a data breakpoint, but data breakpoints do not appear in the source window. Once you have created a data breakpoint, you cannot view, set, enable, disable, delete, or edit it from the source window. If you need to perform one of those operations on a data breakpoint, use the Breakpoints window.

The following list shows the breakpoint operations you can perform from this window:

  • Insert a file breakpoint
  • Insert a function breakpoint
  • Insert an address breakpoint
  • Insert a data breakpoint
  • Delete a breakpoint
  • Enable or disable a breakpoint
  • Edit a breakpoint

See Also

Breakpoints


Inserting a Function Breakpoint In a Source Window

To insert a function breakpoint

  1. In the source window, right-click on the name of the function where you want to insert a breakpoint.
  2. Select New Breakpoint from the shortcut menu.

    The New Breakpoint dialog box appears with the Function tab enabled. The name of the function you selected should appear in the Function box and the language the function is implemented in should appear in the Language box. By default, the Line and Character columns are set to 1. If you accept these default values, the breakpoint will be set at the beginning of the function.

  3. If you want to change any of the default settings, edit them now.
  4. Click OK.

See Also

Breakpoint Operations In A Source Window


Inserting A File Breakpoint In The Source Window

The most intuitive type of breakpoint in a source window is the file breakpoint. A file breakpoint is set at a location in the source file.

To insert a file breakpoint in a source window

  1. In the source window, click on the line where you want to insert the breakpoint.
  2. From the Debug toolbar, choose the Insert Breakpoint tool.

    — or —

    Right-click and choose Insert Breakpoint from the shortcut menu.

This action inserts a file breakpoint at the beginning of the chosen line. In most cases, this is sufficient. Sometimes, however, a line contains more than one statement. In that case, you may need to set the breakpoint somewhere other than the beginning of the line. After you have inserted the breakpoint, you can move it to a specific column (character) within the line:

To move the breakpoint within the line

  1. Right-click on the line where you have set the breakpoint, and select Breakpoint Properties from the shortcut menu.
  2. In the Breakpoint Properties dialog box, choose the File tab and select the Character box.

    The value in the Character box is normally 1 by default.

  3. Edit the value in the Character box to the character where you want to set the breakpoint.
Note If you try to set a breakpoint on a line that does not contain executable code, the debugger automatically moves the breakpoint to the next line that contains executable code. You cannot set a breakpoint inside an attribute. If you try to set a breakpoint on an attribute, the debugger automatically moves the breakpoint to the next line that contains executable code.

See Also

Breakpoint Operations In A Source Window


Deleting a Breakpoint In a Source Window

In a source window, you can view file, function, or address breakpoints as symbols in the left margin. You can delete these breakpoints using the procedure given below. You cannot view data breakpoints in a source window, so you cannot delete a data breakpoint from a source window. To delete a data breakpoint, use the Breakpoints window.

To delete a file, function, or address breakpoint

  1. Right-click on the line containing the breakpoint symbol (A solid dot or empty circle, depending on the breakpoint state).
  2. From the shortcut menu, choose Remove Breakpoint.

See Also

Breakpoint Operations In A Source Window


Editing a Breakpoint In a Source Window

In a source window, you can view file, function, or address breakpoints as symbols in the left margin. You can edit the properties of these breakpoints using the procedure given below. You cannot view data breakpoints in a source window, so you cannot edit their properties from a source window. To edit a data breakpoint, use the Breakpoints window.

To delete a file, function, or address breakpoint

  1. Right-click on the line containing the breakpoint symbol (A solid dot or empty circle, depending on the breakpoint state).
  2. From the shortcut menu, choose Edit Breakpoint Properties.

    The Breakpoint Properties dialog box appears.

  3. In the Breakpoint Properties dialog box, edit the breakpoint properties you want to change.
  4. Click OK.

See Also

Breakpoint Operations In A Source Window


Enabling/Disabling a Breakpoint In a Source Window

In a source window, you can view file, function, or address breakpoints as symbols in the left margin. You can enable or disable these breakpoints using the procedures given below. You cannot view data breakpoints in a source window, so you cannot enable or disable data breakpoints from a source window. To enable disable a data breakpoint, use the Breakpoints window.

When you set a breakpoint, it is enabled by default. The breakpoint remains enabled until you disable it.

To disable a file, function, or address breakpoint

  1. Right-click on the line containing an enabled breakpoint symbol (A solid dot).
  2. From the shortcut menu, choose Disable Breakpoint.
  3. The breakpoint symbol becomes an empty circle.
  4. Once you have disabled a breakpoint, you can reenable it by similar procedure:

To enable a file, function, or address breakpoint

  1. Right-click on the line containing an enabled breakpoint symbol (An empty circle).
  2. From the shortcut menu, choose Enable Breakpoint.
  3. The breakpoint symbol becomes an solid dot.

See Also

Breakpoint Operations In A Source Window


Breakpoint Operations In The Disassembly Window

In the Disassembly Window, you can view, set, enable, disable, delete, or edit a file, function, or address breakpoint. You can insert a data breakpoint, but data breakpoints do not appear in the Disassembly window. Once you have created a data breakpoint, you cannot view, set, enable, disable, delete, or edit it from the Disassembly window. If you need to perform one of those operations on a data breakpoint, use the Breakpoints window.

The following list shows the breakpoint operations you can perform from this window:

  • Insert a file breakpoint
  • Insert a function breakpoint
  • Insert an address breakpoint
  • Insert a data breakpoint
  • Delete a breakpoint
  • Enable or disable a breakpoint
  • Edit a breakpoint

See Also

Breakpoints


Inserting an Address Breakpoint In the Disassembly Window

To insert an address breakpoint in the Disassembly window

  1. In the disassembly code, right click on the line where you want to set the address breakpoint.
  2. From the shortcut menu, choose Insert Breakpoint.

See Also

Breakpoint Operations In the Disassembly Window


Deleting a Breakpoint In the Disassembly Window

In the Disassembly window, you can view file, function, or address breakpoints as symbols in the left margin. You can delete these breakpoints using the procedure given below. You cannot view data breakpoints in the Disassembly window, so you cannot delete a data breakpoint from the Disassembly window. To delete a data breakpoint, use the Breakpoints window.

To delete a file, function, or address breakpoint

  1. Right-click on the line containing the breakpoint symbol (A solid dot or empty circle, depending on the breakpoint state).
  2. From the shortcut menu, choose Remove Breakpoint.

See Also

Breakpoint Operations In the Disassembly Window


Enabling/Disabling a Breakpoint In the Disassembly Window

In the Disassembly window, you can view file, function, or address breakpoints as symbols in the left margin. You can enable or disable these breakpoints using the procedures given below. You cannot view data breakpoints in the Disassembly window, so you cannot enable or disable data breakpoints from the Disassembly window. To enable or disable a data breakpoint, use the Breakpoints window.

When you set a breakpoint, it is enabled by default. The breakpoint remains enabled until you disable it.

To disable a file, function, or address breakpoint

  1. Right-click on the line containing an enabled breakpoint symbol (A solid dot).
  2. From the shortcut menu, choose Disable Breakpoint.

    The breakpoint symbol becomes an empty circle.

Once you have disabled a breakpoint, you can reenable it by similar procedure:

To enable a file, function, or address breakpoint

  1. Right-click on the line containing an enabled breakpoint symbol (An empty circle).
  2. From the shortcut menu, choose Enable Breakpoint.
  3. The breakpoint symbol becomes a solid dot.

See Also

Breakpoint Operations In the Disassembly Window


Editing a Breakpoint In the Disassembly Window

In the Disassembly window, you can view file, function, or address breakpoints as symbols in the left margin. You can edit the properties of these breakpoints using the procedure given below. You cannot view data breakpoints in the Disassembly window, so you cannot edit their properties from the Disassembly window. To edit a data breakpoint, use the Breakpoints window.

To edit a file, function, or address breakpoint

  1. Right-click on the line containing the breakpoint symbol (A solid dot or empty circle, depending on the breakpoint state).
  2. From the shortcut menu, choose Edit Breakpoint Properties.

    The Breakpoint Properties dialog box appears.

  3. In the Breakpoint Properties dialog box, edit the breakpoint properties you want to change.
  4. Click OK.

See Also

Breakpoint Operations In the Disassembly Window


Breakpoint Operations In the Call Stack Window

In the Call Stack Window, you can set a breakpoint on a specific function call on the stack.

To set a breakpoint on a function call

  • In the Call Stack window, right-click on the function call and choose Insert Breakpoint from the shortcut menu. (The program you are debugging must be in a break in a break state.)

    A breakpoint symbol appears in the left margin next to the function call name. The symbol is a solid red dot.

The breakpoint is set at the end of the function call. When the selected call ends, the breakpoint will be hit. When you view the breakpoint properties, this breakpoint appears as an address breakpoint with a memory location corresponding to the end point of the function.

In addition, you perform these other breakpoint operations in the Call window:

  • Delete a breakpoint
  • Enable or disable a breakpoint
  • Edit a breakpoint

See Also

Breakpoints


Deleting a Breakpoint In the Call Stack Window

In the Call Stack window, breakpoints symbols appear in the left margin next to the name of the function call where they are set. You can delete a breakpoint using the procedure given below.

To delete a breakpoint in the Call Stack window

  1. Right-click on the line containing the breakpoint symbol (A solid dot or empty circle, depending on the breakpoint state).
  2. From the shortcut menu, choose Remove Breakpoint.

See Also

Breakpoint Operations In the Call Stack Window


Enabling/Disabling a Breakpoint In the Call Stack Window

In the Call Stack window, breakpoints symbols appear in the left margin next to the name of the function call where they are set. You can disable or enable a breakpoint using the procedure given below.

To disable a breakpoint in the Call Stack window

  1. Right-click on the line containing an enabled breakpoint symbol (A solid dot).
  2. From the shortcut menu, choose Disable Breakpoint.

    The breakpoint symbol becomes an empty circle.

Once you have disabled a breakpoint, you can reenable it by similar procedure:

To enable a file, function, or address breakpoint

  1. Right-click on the line containing an enabled breakpoint symbol (An empty circle).
  2. From the shortcut menu, choose Enable Breakpoint.
  3. The breakpoint symbol becomes a solid dot.

See Also

Breakpoint Operations In the Call Stack Window


Editing a Breakpoint in the Call Stack Window

In the Call Stack window, breakpoints symbols appear in the left margin next to the name of the function call where they are set. You can edit the properties of a breakpoint using the procedure given below

To edit a breakpoint

  1. Right-click on the line containing the breakpoint symbol (A solid dot or empty circle, depending on the breakpoint state).
  2. From the shortcut menu, choose Edit Breakpoint Properties.

    The Breakpoint Properties dialog box appears.

  3. In the Breakpoint Properties dialog box, edit the breakpoint properties you want to change.
  4. Click OK.

See Also

Breakpoint Operations In the Call Stack Window


Using the Breakpoints Window

The Breakpoints Window lists all breakpoints currently set in your program and displays their properties. In the Breakpoints window, you can set (create) new breakpoints, delete breakpoints, enable or disable breakpoints, edit a breakpoint's properties, or find the source or disassembly code corresponding to a breakpoint.

To display the Breakpoints window

  • From the Debug menu, choose Windows and click Breakpoints.

The Breakpoints window occupies the same frame as the Autos, Locals, and This windows. Tabs at the bottom of the frame allow you to switch from one window to another. The titlebar of the window reflects the current tab.

Viewing Breakpoint Information

The Breakpoints window contains a list of all breakpoints currently set in your program. This list contains three columns of information by default. You can view additional information by adding more columns.

To display additional columns

  • In the toolbar at the top of the Breakpoints window, click the Columns tool and select the name of the column you want to display.

To hide a column

  • In the toolbar at the top of the Breakpoints window, click the Columns tool and deselect the name of the column you want to hide.

Hierarchical Breakpoints

A tree control may appear in the Name column next to certain breakpoints. These are hierarchical breakpoints, which are created when you set a breakpoint request that may spawn additional breakpoints. For example, you might set a breakpoint on a class that gets instantiated four or five times. Each time an object of that class gets created, a new breakpoint instance is created along with it.

Enabling/Disabling Breakpoints

A checkbox appears in the Name column next to each breakpoint. The state of this checkbox tells you whether the breakpoint is enabled or disabled.

To enable or disable a single breakpoint

  • Select or clear the checkbox next to that breakpoint.

To enable or disable a hierarchical breakpoint and its children

  • Select or clear the checkbox next to the hierarchical breakpoint.

Setting, Deleting, and Editing Breakpoints

To set a new breakpoint

  1. In the toolbar at the top of the Breakpoints window, choose the New Breakpoint icon.
  2. In the New Breakpoint Dialog Box, choose the type of breakpoint and the options you want.
  3. Click OK.

To delete a breakpoint

  1. In the Breakpoints window, click on the breakpoint you want to delete.
  2. In the toolbar at the top of the window, choose the Delete tool.

To edit a breakpoint

  1. In the Breakpoints window, click on the breakpoint you want to edit.
  2. In the toolbar at the top of the window, choose the Properties tool.
  3. In the Breakpoint Properties dialog box, choose the type of breakpoint and the options you want.
  4. Click OK.

Viewing The Location Of a Breakpoint

For breakpoints that are set on a location, you can view the breakpoint location in the source file or disassembly code. (A breakpoint set on a variable, called a data breakpoint, has no such location.)

To view the location of a breakpoint in the source code

  1. In the Breakpoints window, click on the breakpoint you want to view.
  2. In the toolbar at the top of the window, choose the Go To Source Code tool.

To view the location of a breakpoint in the disassembly code

  1. In the Breakpoints window, click on the breakpoint you want to view.
  2. In the toolbar at the top of the window, choose the Go To Disassembly tool.

If you select a data breakpoint in the Breakpoints window, the Go To Source Code and Go To Disassembly tools are disabled.

See Also

Breakpoints


Why Do Breakpoints Fail When Multiple Source Files Have the Same Name?

If two or more source files in the project have the same name, the debugger may have trouble determining which file the breakpoint is set in. This often happens if you create a module with the same name as a component of the Debug library you are linking to.

To fix this problem, enter the full pathname for the source file. You can change the file name on the File tab of the Breakpoint Properties dialog box.

See Also

Breakpoints


Inspecting Your Program

The primary purpose of any debugger is to display information about the state of the program being debugged and, in some cases, to modify that state. The Visual Studio debugger provides a variety of tools for inspecting and modifying the state of your program.

One of the least obtrusive tools is the DataTips pop-up information box. When your program is in a break state, you can view the value of a variable within the current scope by placing the mouse pointer over the variable in a source window. A DataTips pop-up box appears. To view the value of an expression, select the expression. DataTips pop-up information is not available for expressions outside the current scope or invalid expressions, such as division by zero.

For more detailed inspection of your program, the Visual Studio debugger provides a variety of windows and dialog boxes:

You can use... | To view...
Autos window
  • Variables in the current statement and previous statement
Locals window
  • Local variables
This window
  • Object point to by this
QuickWatch dialog box
  • Variables
  • Register contents
  • Any valid expression recognized by the debugger
Watch window
  • Variables
  • Register contents
  • Any valid expression recognized by the debugger
Registers window | Register contents
Memory window | Memory Contents
Call Stack window
  • Names of functions on the call stack
  • Parameter types
  • Parameter values
Disassembly window | Assembly code generated by the compiler for your program
Threads window | Information on threads (sequential streams of execution) created by your program
Modules window | Modules (DLLs and EXEs) used by your program
Running Documents Window | A list of documents loaded into the current process.

See Also

Listing Commands | Using the Debugger


Using the QuickWatch Dialog Box

To open the QuickWatch dialog box

  • From the Debug menu, choose QuickWatch. (The debugger must be in a break state.)

    — or —

  • In a source window, right-click on a variable name and choose QuickWatch from the shortcut menu. This automatically places the variable into the QuickWatch dialog box. (The debugger must be in a break state.)

As the name implies, you can use QuickWatch to quickly evaluate a variable or expression.

You can also use QuickWatch to edit the value of a variable or register. (You cannot edit the value of const variables. You can edit and display register values for native-code applications only.)

QuickWatch is a modal dialog box. You cannot leave it open to watch a variable or expression while you step through your program. If you need to do that, use the Watch window. You can add variables or expressions to the Watch window from the QuickWatch dialog box.

If you want to save a variable or expression you have been examining in QuickWatch, you can add it to the Watch window.

See Also

QuickWatch Dialog Box | Inspecting Your Program


Evaluating An Expression In QuickWatch

To evaluate a variable, register, or expression

  1. In the QuickWatch dialog box, type or paste the variable, register or expression into the Expression text box.
Tip If the register name happens to match a symbol name, use the @ symbol as a prefix to the register name.
Tip You can change the display format by typing a format specifier following the expression.
Tip You can use the context operator to specify the exact context of a variable or expression. This can be useful, for example, if you want to watch a variable outside the current scope.
  1. Click Recalculate.
  2. The value appears in the Current value box.
  3. If you typed an the name of an array or object variable in the Expression box, a tree control appears next to the name in the Current value box. Click on the plus (+) or minus (–) in the Name column to expand or collapse the variable.

To save the trouble of retyping a previous expression, you can choose it from the dropdown list attached to the Expression box.

To reenter a previous expression

  1. Click on the down arrow at the right of the Expression box.
  2. Choose the expression from the dropdown list.
  3. Click Recalculate.

You can display register values for native-code applications only.

See Also

Using the Quickwatch Dialog Box


Editing a Value In QuickWatch

To change the value of a variable or register

  1. Type the variable or register name in the Expression text box.
Tip If the register name happens to match a symbol name, use the @ symbol as a prefix to the register name.
  1. Click Recalculate.
  2. If you typed the name of an array or object variable in the Expression box, a tree control appears next to the name in the Current value box. Click on the plus (+) or minus (–) in the Name column to expand or collapse the variable to find the element whose value you want to edit.
  3. Double-click in the Value column of the Current value box to select the value.
  4. Use the mourse and keyboard to edit the value.
  5. Press ENTER.
Caution Editing floating-point values can result in minor inaccuracies due to decimal-to-binary conversion of fractional components. Even a seemingly innocuous edit can result in changes to some of the least significant bits in a floating-point variable.

You cannot edit the value of const variables. You can edit and display register values for native-code applications only.

See Also

Using the Quickwatch Dialog Box


Adding a QuickWatch Expression To the Watch Window

To add a variable or expression to the Watch window

  1. In the QuickWatch dialog box, enter the variable or expression in the Expression box.
  2. Click the Add Watch button.

See Also

Using the Quickwatch Dialog Box


Using the Watch Window

To display the Watch window

  • From the Debug menu, choose Windows and click Watch. (The debugger must be running or in a break state.)

You can use the Watch window to evaluate variables and expressions and keep the results. You can also use the Watch window to edit the value of a variable or register. (You cannot edit the value of const variables. You can edit and display register values for native-code applications only.)

Tip The QuickWatch dialog box provides a quicker, simpler way of evaluating or editing a single variable or expression.

See Also

Watch Window | Inspecting Your Program


Evaluating an Expression In the Watch Window

To evaluate a variable, register, or expression

  1. The debugger must be in a break state.
  2. In the Watch window, double-click on an empty row in the Name column.
  3. Type or paste the variable, register or expression in the selected row.
Tip If the register name happens to match a symbol name, use the @ symbol as a prefix to the register name.
Tip You can change the display format by typing a format specifier following the expression.
Tip You can use the context operator to specify the exact context of a variable or expression. This can be useful, for example, if you want to watch a variable outside the current scope.
  1. Press ENTER.
  2. The result appears in the Value column. If you typed the name of an array or object variable, a tree control appears next to the name in the Name column. Click on the plus (+) or minus (–) in the Name column to expand or collapse the variable.
  3. The expression remains in the Watch window until you remove it or until you end the debugging session.

You can display register values for native-code applications only.

See Also

Using the Watch Window


Editing a Value In the Watch Window

To evaluate a variable, register, or expression

  1. The debugger must be in a break state.)
  2. If you typed the name of an array or object variable in the Expression box, a tree control appears next to the name in the Current value box. Click on the plus (+) or minus (–) in the Name column to expand or collapse the variable to find the element whose value you want to edit.
  3. Double-click the Value column, in the row corresponding to the variable or expression whose value you want to change.
  4. Use the mouse and keyboard to edit the value.
  5. Press ENTER.

You cannot edit the value of const variables. You can edit and display register values for native-code applications only.

See Also

Using the Watch Window


Using the Locals Window

To display the Locals window

  • From the Debug menu, choose Windows and click Locals. (The debugger must be running or in a break state.)

The Locals window displays variables local to the current context. The default context is the function containing the current execution location. Alternative contexts are other functions in the chain that called the current function.

To choose an alternative context

  • Select a context from the list box on the toolbar at the top of the Locals window.

To view or modify information in the Locals window, your program must be in a break state. If you choose Continue, some information may appear in the Locals window while your program executes, but it will not be current until the next time your program breaks (in other words, it hits a breakpoint or you choose Break from the Debug menu).

To modify the value of a variable in the Locals window

  1. Your program must be in a break state.
  2. In the Locals window, select the value you want to edit by double-clicking on it or by using the TAB key.
  3. Type the new value, and press ENTER.
Caution Editing floating-point values can result in minor inaccuracies due to decimal-to-binary conversion of fractional components. Even a seemingly innocuous edit can result in changes to some of the least significant bits in the floating-point variable.

See Also

Locals Window | Viewing and Modifying Data | Using the This Window | Using the Autos Window


Using the Autos Window

To display the Autos window

  • From the Debug menu, choose Windows and click Autos. (The debugger must be running or in a break state.)

The Autos window displays variables used in the current statement and the previous statement. The current statement is the statement at the current execution location (the statement that will be executed next if execution continues). The debugger identifies these variables for you automatically, hence the window name.

Structure and array variables have a tree control that you can use to display or hide the elements.

To modify the value of a variable in the Autos window

  1. Your program must be in a break state.
  2. Display the Autos window, if necessary.
  3. In the Value column, double-click on the value you want to change

    — or —

    Single-click to select the line, then press the TAB key.

  4. Type the new value, and press ENTER.
Caution Editing floating-point values can result in minor inaccuracies due to decimal-to-binary conversion of fractional components. Even a seemingly innocuous edit can result in changes to some of the least significant bits in the floating-point variable.

See Also

Autos Window | Inspecting Your Program


Using the This Window

To display the This window

  • From the Debug menu, choose Windows and click this. (The debugger must be running or in a break state.)

Using the This window, you can examine the data members of the object pointed to by the C++ this pointer or the Visual Basic me object.

To modify the value of a variable in the This window

  1. Your program must be in a break state.
  2. In the This window, select the value you want to edit by double-clicking on it or by using the TAB key.
  3. Type the new value, and press ENTER.
Caution Editing floating-point values can result in minor inaccuracies due to decimal-to-binary conversion of fractional components. Even a seemingly innocuous edit can result in changes to some of the least significant bits in the floating-point variable.

See Also

This Window | Viewing and Modifying Data


Using the Registers Window

To display the Registers window

  • From the Debug menu, choose Windows and click Registers. (The debugger must be running or in a break state.)
    Note Register information is available for native-code applications only.

The Registers window displays register contents. If you keep the Registers window open as you step through your program, you can see register values change as your code executes. Values that have changed recently appear in red.

To reduce clutter, the Registers window organizes registers into groups. You can display or hide groups as you see fit.

You can edit the value of a register in the Registers window. If you choose to display the register flags group, you can edit register flags. For Intel x86 processors, you can set the following register flags:

Register Window Flags

Flag | Set Value
Overflow | O = 1
Direction | D = 1
Interrupt | I = 1
Sign | S = 1
Zero | Z = 1
Auxiliary carry | A = 1
Parity | P = 1
Carry | C = 1

See Also

Registers Window | Inspecting Your Program


Displaying/Hiding Register Groups

To display or hide register groups

  1. Right-click on the Registers window.
  2. From the short-cut menu, select Register Groups and choose the groups you want to show or hide.

See Also

Using the Registers Window


Editing a Register Value

To change the value of a register

  1. In the Registers window, use the TAB key or the mouse to move the insertion point to the value you want to change. When you start to type, the cursor must be located in front of the value you want to overwrite.
  2. Type the new value.
  3. Press ENTER.
Caution Changing register values (especially in the EIP and EBP registers) can affect program execution.
Caution Editing floating-point values can result in minor inaccuracies due to decimal-to-binary conversion of fractional components. Even a seemingly innocuous edit can result in changes to some of the least significant bits in a floating-point register.

See Also

Using the Registers Window


Using the Memory Window

Note This feature is available for native-code applications only.

You can use a Memory window to view large buffers, strings, and other data that do not display well in the Watch or Variables window. In the Visual Studio debugger, you can open up to four Memory windows.

To display a Memory window

  • From the Debug menu, choose Windows, then Memory, and click on Memory 1, Memory 2, Memory 3, or Memory 4. You can open these memory windows in any order; it doesn't matter. (The debugger must be running or in a break state.)

When viewing memory contents in a Memory window, you can use the vertical scrollbar to move up or down in the memory space. You will notice that the higher addresses appear at the bottom of the window. To view a higher address, you must move down, not up.

To page up or down in memory

  • To page down (move to a higher memory address), click the vertical scrollbar below the thumb.
  • To page up (move to a lower memory address), click the vertical scrollbar above the thumb.

You will also notice that the vertical scrollbar operates in a nonstandard fashion. The address space of a modern PC is huge, and it would be easy to get lost by grabbing the scrollbar thumb and dragging it to a random location. For this reason, the thumb is "springloaded" and always remains in the center of the scrollbar. You can page up or down, but cannot scroll about freely.

If you want to move instantly to a selected location in memory, you can do so by using drag and drop or editing the value in the Address box.

The Address box accepts expressions as well as numeric values. By default, the Memory window treats an Address expression as a live expression, which is reevaluated as your program executes. Live expressions can be quite handy. For example, you can use them to look at the memory that is touched by a pointer.

You can also use register names as live expressions. You can use a register expression to follow the stack, for example.

If you don't want the contents of the Memory window to change as your program executes, you can turn off live expression evaluation.

You can customize the way the Memory window shows memory contents. By default, memory contents appear as long data types in hexadecimal format, and the number of columns is determined automatically by the current width of the window.

You can hide or display the toolbar at the top of the Memory window. (You will not have access to Address box or other tools while the toolbar is hidden.)

See Also

Memory Window | Inspecting Your Program


Following a Pointer Through Memory

To follow a pointer through memory

  1. In the Memory window Address box, type a pointer expression, such as *pnB. (The pointer variable must be within the current scope.)
  2. Press ENTER.

    Now, when you use an execution command, such as Step, the memory address displayed will automatically change as the pointer changes.

See Also

EnterLinks


Following the Stack Contents

To follow the contents of the stack

  1. In the Memory window Address box, type ESP (the stack pointer register).
  2. Press ENTER.

See Also

EnterLinks


Selecting a Memory Location

To select a memory location using drag-and-drop

  1. From any window, select a memory address or pointer variable containing a memory address.
  2. Drag the address or pointer to the Memory window, and drop it.

To select a memory location by editing

  1. In the Memory window, select the Address box.
  2. Type or paste the address you want to see and press ENTER.

See Also

Using the Memory Window


Toggling Live Evaluation In the Memory Window

To toggle live evaluation on or off

  1. Right-click on the Memory window.
  2. From the short-cut menu, click Reevaluate Automatically.

    If live evaluation is on, the option will be checked, and clicking it turns live evaluation off. If live evaluation is off, the option is not checked, and clicking it turns live evaluation on.

See Also

Using the Memory Window


Customizing the Memory Window Display

To change the format of the memory contents

  1. Right-click on the Memory window.
  2. From the short-cut menu, choose the format you want .

To change the number of columns in the Memory window

  1. In the toolbar at the top of the Memory window, find the Columns list.
  2. From the Columns list, toolbar at the top of the Memory window, choose the number of columns you want to display or choose Auto for automatic adjustment to fit the width of the window.

See Also

Using the Memory Window


Toggling the Memory Window Toolbar

To toggle the toolbar

  1. Right-click on the Memory window.
  2. From the short-cut menu, click Toolbar.

    The toolbar appears or disappears, depending on its previous state.

See Also

Using the Memory Window


Using the Call Stack Window

To display the Call Stack window

  • From the Debug menu, choose Windows and click Call Stack. (The debugger must be running or in a break state.)

Using the Call Stack window, you can view the function or procedure calls that are currently on the stack. The Call Stack window displays the name of each function and the programming language it is written in. The function or procedure name may be accompanied by optional information, such as module name, line number, byte offset, and parameter names, types, and values. The display of this optional information can be turned on or off:

To change the optional information displayed

  • Right-click on the Call Stack window and set or clear Show <the desired information> from the shortcut menu.

By default, the Call Stack window does not display calls to or from another thread. If you want to see those calls, you can:

To display calls to or from another thread

  • Right-click on the Call Stack window and choose Include Calls To/From Other Threads from the shortcut menu.

    You can also use the shortcut menu to quickly view the source or disassembly code for a function that appears on the call stack:

To view the source code for a function on the call stack

  • In the Call Stack window, right-click on the function whose source code you want to see and choose Go To Source Code from the shortcut menu.

To view the disassembly code for a function on the call stack

  • In the Call Stack window, right-click on the function whose disassembly code you want to see and choose Go To Disassembly from the shortcut menu.

    Here are some useful techniques you can use in the Call Stack window:

  • Running to a specific function
  • Setting a breakpoint on the exit point of a function call

See Also

Call Stack Window | Inspecting Your Program


Using the Disassembly Window

To display the Disassembly window

  • From the Debug menu, choose Windows and click Disassembly. (The debugger must be running or in a break state.)

The Disassembly window shows assembly code corresponding to the instructions created by the compiler. In addition, it can show the following optional information:

  • Memory address where each instruction is located. (For native applications, this is the actual memory address. For C# or managed code, it is a pseudomemory address where the beginning of the application's memory space is location zero.)
  • Source code from which the assembly code derives
  • Code bytes (byte representations of the actual machine-code instructions)
  • Symbols names for the memory addresses
  • Line numbers corresponding to the source code

To turn optional information on or off

  • Right-click in the Disassembly window and set or clear the desired options in the shortcut menu.

A yellow arrow in the left margin shows the location of the current execution point. For native code, this corresponds to the CPU's program counter. This location shows the next instruction that will be executed in your program.

Navigating the Memory Space

To page up or down in the memory space

  • Click the vertical scrollbar, above or below the thumb.

You can't scroll by dragging the thumb up or down, as you can with ordinary scrollbars. Due to the huge size of the memory space on modern computers, scrolling would likely cause you to overshoot any area of memory you were looking for. So, the thumb acts as if it were spring loaded and always remains in the center of the scrollbar.

Notice that higher memory addresses appear at the bottom of the window, so if you want to view a higher address, you must page down.

To move up or down one instruction

  • Click the arrow at the top or bottom of the vertical scrollbar.

See Also

Disassembly Window | Inspecting Your Program


Using the Threads Window

To display the Threads window

  • From the Debug menu, choose Windows and click Threads. (The debugger must be running or in a break state.)

With the Threads window, you can examine and control threads in the program you are debugging. A thread is a sequence of executable instructions created by a program. A program can be single threaded or multithreaded. On single-processor systems, only one thread can be actively running at a time — this is called the active thread.

When you debug a multithreaded program, you can use the Threads window to view thread information and manipulate threads. From the Threads window, you can set the active thread and freeze or thaw the execution of a thread. Freezing prevents the execution of a thread and thawing allows it. "Frozen" and "thawed" are states set by the debugger, and are independent of the Suspend count, which is set by the program.

To set an active thread

  • In the Threads window, right click on a thread and choose Set As Active from the context menu.

To freeze (prevent execution of) a thread

  • In the Threads window, right click on a thread and choose Freeze from the shortcut menu.

To thaw (allow execution of) a thread

  • In the Threads window, right click on a thread and choose Thaw from the shortcut menu.

In some cases, the debugger can freeze a thread without your specifically requesting it. If you select the Break command while your program is deadlocked in the kernel, the debugger will timeout after a few seconds and perform a "soft break." The debugger freezes all threads. A "soft break" resembles a normal break, but stepping is not possible. A message box informs you when a soft break occurs.

Tips for Debugging Threads

Tip When debugging native Win32 code, you can view the contents of the Thread Information Block by entering the pseudoregister @TIB in the Watch window or QuickWatch dialog. For information on Thread Information Blocks, see "Under the Hood" in the May 1996 edition of the Microsoft Systems Journal.
Tip When debugging native Win32 code, you can view the last error code for the current thread (the value returned by a call to (GetLastError) by entering the pseudoregister @Err in the Watch window or QuickWatch dialog.
Tip For an example showing how to use CRT functions for debugging a multithreaded application, see the code in the CRT topic _malloc_dbg.

See Also

Threads Window | Inspecting Your Program


Using the Modules Window

To display the Modules window

  • From the Debug menu, choose Windows and click Modules. (The debugger must be running or in a break state.)

The Modules window lists the modules (DLLs and EXEs) used by your program and shows relevant information for each.

By default, the Modules window sorts modules by load order. You can choose to sort by any column, however.

To sort by any column

  • Click on the button at the top of the column.

See Also

Modules Window | Inspecting Your Program


Using the Running Documents Window

The Running Documents window is useful for script debugging. It displays a list of documents that are currently loaded into the process you are running. For example, if you add an HTML frameset, the Running Documents window shows you which pages are currently loaded in the browser.

In the Running Documents window you can:

  • Double-click on a document to display an editor window for that document.
  • Expand and collapse the list to see the pages or documents within the top-level documents.

See Also

Running Documents Window | Inspecting Your Program


Displaying Elements of a Custom Data Type

When you are using interface elements such as the Watch window, the Visual Studio debugger automatically expands common data types to show their most important elements. If you have your own custom data types that you want the debugger to autoexpand, you can add rules to the file autoexp.dat, which is located in the /bin directory. Instructions on how to write autoexp rules are located in the file itself. The structure of this file and the syntax of autoexp rules may change from one release of Visual C++ to the next.

See Also

Inspecting Your Program


Handling Exceptions

An exception is an abnormal situation that happens while a program is running. Exceptions are often indications of problems that you need to debug. The Visual Studio debugger recognizes many types of exceptions. These include C++ exceptions, NGWS runtime exceptions, Win32 exceptions, and C Run-time Errors. Some types of exceptions, such as C++ exceptions, have handlers — pieces of code that are designed to respond to an exception when it occurs, giving the program a chance to recover from the abnormal situation. C runtime errors do not have handlers.

When an exception occurs, the debugger writes an exception messages to the Output window. The debugger can also break execution of the program when an exception occurs, giving you a chance to debug it. You can choose whether or not you want the debugger to break on a given type of exception or category of exceptions.

To change how the debugger handles an exception or category of exceptions

  1. From the Debug menu, click Exceptions.

    The Exceptions dialog box opens.

  2. In the Exceptions list, use the tree control to select the individual exception or category of exceptions whose handling you want to change.
  3. Under When the exception is thrown:
    • Choose Break into the debugger if you want execution to break as soon as the exception occurs, without giving the handler a chance to execute. If you choose this setting, the icon next to the exception or category name appears as a large red ball with an "X" through it.
    • Choose Continue to give the handler a chance to fix the problem. If you choose this setting, the icon next to the exception or category name appears as a large red ball with an "X" through it. If you choose this setting, the icon next to the exception or category name appears as a large gray ball.
    • Choose Use parent setting to accept the default setting currently specified for the category which the exception is part of. (This option is not available if you chose a category, rather than an individual exception, in step 2.) If you choose this setting, the icon next to the exception or category name appears as a small gray ball.

    The icon next to an exception name (or category name) changes to reflect the setting for When the exception is t

  4. Under If the exception is not handled:
    • Choose Break into the debugger if you want execution to break after the handler executes if the handler is not successful in fixing the problem.
    • Choose Continue if you want execution to continue after the handler executes, regardless of whether the handler is successful or not.
    • Choose Use parent setting to accept the default setting currently specified for the category which the exception is part of. (This option is not available if you chose a category, rather than an individual exception, in step 2.)
  5. Choose the option.
  6. Click OK.

When the debugger breaks on an exception, you can look at the source window to see where the exception occurred, use the Watch and Variables windows and QuickWatch to see variable contents, and attempt to fix the exception yourself by modifying the variable contents. If you continue execution of the after an exception, a dialog box asks if you want to pass the exception back to the handler. At that point you have three options:

  • You can click No. This is the option you usually want to pick if you successfully fixed the problem.
  • You can click Yes, and the exception handler will be invoked. If the exception handler cannot fix the problem, the debugger halts the program and notifies you.
  • You can click Cancel, in which case debugging and program execution end.

By default, the Exceptions dialog box lists the most common exceptions in each category. You can add other exceptions to a category. These exceptions are stored with the project and will be available the next time you open and run the project.

You can delete user-added exceptions from the list. There's also a procedure for deleting all user-added exceptions. You cannot delete the default exceptions, however.

See Also

Exceptions Dialog Box | Using the Debugger


Adding a New Exception

To add a new exception to the Exceptions list

  1. In the Exceptions list of the Exceptions dialog, choose a top-level category (such as NGWS Runtime Exceptions). This is the category you will add the exception to.

    The Add button becomes enabled.

  2. Click the Add button.

    The New Exception dialog box appears.

  3. Type the exception name in the Name box.
  4. Click OK.

    The new exception appears in the Exceptions list.

See Also

Handling Exceptions


Deleting a User-Added Exception

To delete a user-added exception

  1. In the Exceptions dialog box, select the exception you want to delete in the Exceptions box.
  2. Click Delete.

    It's gone.

See Also

Deleting All User-Added Exceptions | Handling Exceptions


Deleting All User-Added Exceptions

To delete all user-added exceptions

  • In the Exceptions dialog box, click Clear All.

See Also

Deleting a User-Added Exception | Handling Exceptions


Using C Run-Time Error Checks

In Visual C++, you can use run-time error checks to catch common run-time errors such as:

  • Stack Pointer corruption.
  • Overruns of local arrays.
  • Stack corruption.
  • Dependencies on uninitialized local variables.
  • Loss of data on an assignment to a shorter variable.

To enable run-time error checks in a debug build, use the /RTC option and link with the debug version of a C run-time library (/MDd, for example). You can modify run-time error check behavior with the run-time_checks pragma.

You cannot use /RTC with an optimized (/O) build. A compiler error results. If you use a run-time_checks pragma in an optimized build, the pragma has no effect.

When you debug a program with run-time error checks enabled, the default action is for the program to stop and break to the debugger when a run-time error occurs. You can change this default behavior for any run-time check. For details, see Handling Exceptions.

Note Run-time error checking tracks memory allocation and deallocation only if the allocation and deallocation is done with C allocators (malloc, calloc, realloc, and free) or global C++ allocators (new, new[], delete, and delete[]). Memory leak and pointer type checking also depend on the proper use of these allocators and deallocators. If you use other functions for allocating and deallocating memory, you cannot count on runtime error checking to catch these problems unless you write your own reporting functions.

What do you want to know more about?

  • Customizing Run-Time Checks with the C Run-Time Library
  • Using Run-Time Checks without the C Run-Time Library

See Also

Debugging Your Program | /RTC compiler option | #pragma run-time_checks | Run-Time Error Checks Function Reference | RTC sample


Customizing CRT Error Checking

The C run-time library provides run-time error checking when you compile with /RTC (run-time checks) or use the run-time_checks pragma. In some cases, you may want to customize CRT run-time error checking:

  • To route run-time error messages to a file or destination other than the default.
  • To specify an output destination for run-time error messages under a third-party debugger.
  • To report run-time error messages from a program compiled with a release version version of the C run-time library. (Release versions of the library do not use _CrtDbgReport to report run-time errors. Instead, they display an Assert dialog box for each run-time error.)

To customize run-time error checking, you can:

  • Write Your Own Function to Report Run-Time Errors
  • Customize the Error Message Destination
  • Query for Information about Run-Time Check Errors

Writing a Run-Time Error Reporting Function

A custom reporting function for run-time errors must have same declaration as _CrtDbgReport. It should return value of 1 to the debugger.

The following example shows how to define a custom reporting function:

int errorhandler = 0;
void configureMyErrorFunc(int i)
{
   errorhandler = i;
}

int MyErrorFunc(int errorType, const char *filename, int linenumber, const char *moduleName, const char *format, ...)
{
   switch (errorhandler)
   {
   case 0:
   case 1:
      printf("Error type %d at %s line %d in %s",errorType. filename, linenumber, moduleName);
   case 2:
   case 3:
      fprintf(stderr, "Error type);
   }
}

The following examples shows a more complex custom reporting function. In this example, the switch statement handles various error types, as defined by the reportType parameter of _CrtDbgReport. Since you are replacing _CrtDbgReport, you cannot use _CrtSetReportMode. Your function must handle the output. The first variable argument in this function takes a run-time error number.

#include <windows.h>
#include <stdarg.h>
#pragma runtime_checks("", off)
int Catch_RTC_Failure(int errType, const char *file, int line, const char *module, const char *format, ...)
{
   // Prevent re-entrancy
   static long running = 0;
   while (InterlockedExchange(&running, 1))
      Sleep(0);
   // Now, disable all RTC failures
   int numErrors = _RTC_GetNumErrors();
   int *errors=_alloca(numErrors);
   for (int i = 0; i < numErrors; i++)
   errors[i] = _RTC_SetErrorType(i, _RTC_ERRTYPE_IGNORE);

   // First, let's get the rtc error number from the var-arg list...
   va_list vl;
   va_start(vl, format);
   _RTC_ErrorNumber rtc_errnum = va_arg(vl, _RTC_ErrorNumber);
   va_end(vl);

   char buf[512];
   const char *err = _RTC_GetErrDesc(rtc_errnum);
   sprintf(buf, "%s\nLine #%d\nFile:%s\nModule:%s",
      err,
      line,
      file ? file : "Unknown",
      module ? module : "Unknown");
   int res = (MessageBox(NULL, buf, "RTC Failed...", MB_YESNO) == IDYES) ? 1 : 0;
   // Now, restore the RTC errortypes
   for(i = 0; i < numErrors; i++)
      _RTC_SetErrorType(i, errors[i]);
   running = 0;
   return res;
}
#pragma runtime_checks("", restore)

Use _RTC_SetErrorFunc to install your custom function in place of _CrtDbgReport. The _RTC_SetErrorFunc return value is the previous reporting function, which you can save and restore if necessary:

int main()
{
   _RTC_error_fn oldfunction, newfunc;
   oldfunction = _RTC_SetErrorFunc(&MyErrorFunc);
   // run some code...
   newfunc = _RTC_SetErrorFunc(oldfunction);
   // newfunc == &MyErrorFunc;
   // run some more code...
}

Customizing the Error Message Destination

If you use _CrtDbgReport to report errors, you can use _CrtSetReportMode to specify the destination of error messages.

If you use a custom reporting function, use _RTC_SetErrorType to associate an error with a report type.

Querying for Information about Run-Time Error Checks

_RTC_NumErrors returns the number of error types detect by run-time error checks . To get a brief description of each error, you can loop from 0 to (_RTC_NumErrors –1) return value, passing the iteration value to _RTC_GetErrDesc on each loop.

See Also

Run-Time Error Checks


Using Run-Time Checks without the C Run-Time Library

If you link your program without the C run-time library (using /NODEFAULTLIB) and want to use run-time error checks, you must link with RunTmChk.lib.

_RTC_InitBase initializes your program for run-time error checks. If you do not link with the C run-time library, you must check to see whether your program is compiled with run-time error checks before calling _RTC_InitBase:

#ifdef __MSVC_RUNTIME_CHECKS
   _RTC_InitBase();
#endif

If you do not link with the C run-time library, you must also define a function called _CRT_RTC_INIT. _CRT_RTC_INIT installs your user-defined function as the default error reporting function:

// C version
_RTC_error_fn __cdecl _CRT_RTC_INIT(void *res0, void **res1, int res2, int res3, int res4);
{
   return &MyErrorFunc; // set the error handler
}

// C++ version
extern "C" _RTC_error_fn __cdecl _CRT_RTC_INIT(void *res0, void **res1, int res2, int res3, int res4);
{
   return &MyErrorFunc; // set the error handler

}

After you have installed the default error reporting function, you can install additional error reporting functions with _RTC_SetErrorFunc.

See Also

Run-Time Error Checks


Edit and Continue

Edit and Continue enables you to change your source code and apply those changes (with some limitations) while your program is running under the Visual Studio debugger (or in a break state). Not only does this save time, it also gives you the chance to see the effect of changes during the current conditions under which your program is running. When you install Visual Studio, Edit and Continue is turned on by default. You can turn it off if you prefer.

To enable/disable Edit and Continue

  1. From the Tools Menu, click Options.
  2. In the Options dialog box, select the Debugging folder.
  3. In the Edit and Continue group, select or clear the Enable Edit and Continue check box.
  4. Click OK.

When you edit code during you are debugging, Edit and Continue can apply the changes:

  • Explicitly, when you select Apply Code Changes from the Debug menu, or
  • Automatically, when you select a Go or Step command.

When you apply code changes explicitly, Edit and Continue updates the compiled code you are debugging, but does not step or resume execution.

If you prefer, you can disable the automatic invocation of Edit and Continue by Go and Step commands. You might do this if you are making edits to the code that you do not want applied during the current debugging session.

To enable/disable automatic invocation of Edit and Continue

  1. From the Tools Menu, click Options.
  2. In the Options dialog box, select the Debugging folder.
  3. In the Edit and Continue group, select or clear the Invoked by debug commands check box.
Note You also have the option of having the debugger ask you before applying code changes prior to a debug command. If you want to be asked, select the Ask me first check box.
  1. Click OK.

Because Invoked by debug commands is a tools option, altering this setting affects all projects you work on. You do not need to rebuild your application after changing this setting. You can change the setting even while debugging. If you build your application from the command line or from a makefile but debug in the Visual C++ environment, you can still use Edit and Continue if you set the /ZI option.

Caution Do not enable Edit and Continue (/ZI) if you are debugging optimized code. Edit and Continue is incompatible with compiler optimizations. The result is a compiler error.

Some code changes cause the point of execution to move to a new location when Edit and Continue applies the changes. Edit and Continue places the point of execution as accurately as possible, but the results may not be correct in all cases. A dialog box informs you when the point of execution changes. You should verify that the location is correct before you continue debugging. If it is not correct, use the Set Next Statement, as described in Setting the Execution Point.

See Also

Using the Debugger


Limitations of Edit and Continue

Edit and Continue places a limit of 64 bytes on the total size of the new variables you can add to an active function. (An active function is any function on the call stack — the current function or one of its callers.) If you exceed this limit, the code changes will be applied the next time the function is called. There is no new-variable limit for functions not currently on the call stack.

Edit and Continue does not handle some types of code changes. The following changes cannot be applied during the debugging session:

  • Changes to resource files
  • Changes to code in read-only files
  • Changes to optimized code (code compiled with /O1, /O2, /Og, /Ox, /Ob1, or /Ob2)
  • Changes to exception-handling blocks
  • Changes to data types, including class, structure, union, or enumeration definitions
  • Removal of functions
  • Most changes to global or static code
  • Changes to executables that are copied from another machine and not built locally

If you make one of these changes and then try to apply code changes or use an execution command, an error message appears in the Output window. Changes to data type definitions and changes to function prototypes produce a compiler error message (C1092).

In some cases, Edit and Continue cannot apply code changes to the executable immediately, but may be able to apply the code changes later if you continue debugging. This occurs if you edit a function that calls the current function or if you add more than 64 bytes of new variables to a function on the call stack. When this happens, the original code continues to execute until the function exits and is called again. Edit and Continue updates the call at that time. Until the call exits, the source window shows the original code in gray. Because this code is has been superceded by code changes, it is outdated or stale. You cannot edit stale code. The debugger warns you about stale code, by default. You can turn the warning off, if you prefer.

To enable/disable the stale code warning

  1. From the Tools Menu, click Options.
  2. In the Options dialog box, select the Debugging folder.
  3. In the Edit and Continue group, select or clear the Warn me about stale code check box.
  4. Click OK.

Tip You can change the color that source windows use to display stale code.

To change the color of superceded code

  1. From the Tools menu, choose Options.
  2. In the Options dialog box, choose the Format tab.
  3. In the Category box, choose Source Windows.
  4. In the Colors box, choose Superceded code.
  5. In the Foreground list box, choose a color.
  6. Click OK.

See Also

Edit and Continue | Attribute Limitations | Linking Limitations | Precompiled Header Limitations


Attribute Limitations

Edit and Continue does not regenerate IDL files; therefore, changes to IDL attributes will not be reflected while you are debugging. To see the result of changes to IDL attributes, you must stop debugging and rebuild your application. Edit and Continue does not generate an error or warning if IDL attributes have changed.

See Also

Limitations of Edit and Continue


Linking Limitations

Edit and Continue has two types of linker limitations:

  • By default, Edit and Continue relinks your program at the end of a debugging session to create an up-to-date executable. There are some Limitations on Automatic Relinking.
  • Some linker options disable Edit and Continue.


Limitations on Automatic Relinking

By default, Edit and Continue relinks your program at the end of a debugging session to create an up-to-date executable.

Edit and Continue cannot relink your program if you are debugging it from a location other than the original build location. An error message (ENC1503) tells you that you need to rebuild manually.

Edit and Continue does not rebuild static libraries. If you make changes to a static library using Edit and Continue, you need to manually rebuild the library and relink applications using it.

Edit and Continue does not invoke custom build steps. If your program uses custom build steps, you may want to rebuild manually so that custom build steps can be invoked. In that case, you can disable relinking after Edit and Continue to ensure that you are prompted to manually rebuild.

To disable relinking after Edit and Continue

  1. From the Tools menu, click Options.
  2. In the Options dialog box, select the Debuging folder and the Edit and Continue group.
  3. Clear the Relink after debugging check box.
  4. Click OK.

In addition, certain linker options disable Edit and Continue.

See Also

Linker Options that Disable Edit and Continue


Linker Options that Disable Edit and Continue

The following linker options disable Edit and Continue.

  • Setting /OPT:REF, /OPT:ICF, or /INCREMENTAL:NO disables Edit and Continue with the following warning:
    LINK : warning LNK4075: ignoring /EDITANDCONTINUE due to /OPT specification
  • Setting /PROFILE, /ORDER, /RELEASE, /FORCE, or /DEBUGTYPE:COFF disables Edit and Continue with this warning:
    LINK : warning LNK4075: ignoring /INCREMENTAL due to /option specification
  • Setting any option that prevents the creation of a program database (.PDB) file disables Edit and Continue with no specific warning.

See Also

Limitations of Edit and Continue


Precompiled Header Limitations

By default, Edit and Continue loads and processes precompiled headers in the background to speed up processing of code changes. Loading precompiled headers requires allocation of physical memory, which can be a problem if you are compiling on a machine with limited RAM. Under Windows NT or Windows 2000, you can determine if this might be a problem by using the Windows NT Task Manager to determine the amount of available physical memory while you are debugging. If this amount is greater than the size of your precompiled headers, Edit and Continue should have no problem. If the amount is less than the size of your precompiled headers, you can prevent Edit and Continue from loading precompiled headers in the background.

To disable background loading of precompiled headers for Edit and Continue

  1. From the Tools menu, click Options.
  2. In the Options dialog box, select the Debugging folder and the Edit and Continue group.
  3. Clear the Allow Precompiling check box.
  4. Click OK.

See Also

Limitations of Edit and Continue


Debugging DLLs

This section covers the following topics:

  • Methods for Debugging DLLs
  • Why Don’t My DLL Breakpoints Work?

See Also

Debugging Your Program


Methods for Debugging DLLs

If you have the source for both the DLL and the calling program, open the project for the calling executable file and debug the DLL from there. If you load a DLL dynamically, you must specify it in the Additional DLLs category of the Debug tab in the Project Settings dialog box.

If you have the source for the DLL only, open the project that builds the DLL. Use the Debug tab in the Project Settings dialog box to specify the executable file that calls the DLL.

You can also debug a DLL without a project. For example, maybe you just picked up a DLL and source code but you don’t have an associated project or workspace. You can use the Open command on the File menu to select the .DLL file you want to debug. The debug information should be in either the .DLL or the related .PDB file. After Visual C++ opens the file, on the Build menu click Start Debug and Go to begin debugging.

To debug a DLL using the project for the executable file

  1. From the Project menu, click Settings.

    The Project Settings dialog box appears.

  2. Choose the Debug tab.
  3. In the Category drop-down list box, select General.
  4. In the Program Arguments text box, type any command-line arguments required by the executable file.
  5. In the Category drop-down list box, select Additional DLLs.
  6. In the Local Name column, type the names of DLLs to debug.

    If you are debugging remotely, the Remote Name column appears. In this column, type the complete path for the remote module to map to the local module name.

  7. In the Preload column, select the check box if you want to load the module before debugging begins.
  8. Click OK to store the information in your project.
  9. From the Build menu, click Start Debug and Go to start the debugger.

You can set breakpoints in the DLL or the calling program. You can open a source file for the DLL and set breakpoints in that file, even though it is not a part of the executable file’s project.

To debug a DLL using the project for the DLL

  1. From the Project menu, click Settings.

    The Project Settings dialog box appears.

  2. Choose the Debug tab.
  3. In the Category drop-down list box, select General.
  4. In the Executable For Debug Session text box, type the name of the executable file that calls the DLL.
  5. In the Category list box, select Additional DLLs.
  6. In the Local Module Name column, type the name of the DLLs you want to debug.
  7. Click OK to store the information in your project.
  8. Set breakpoints as required in your DLL source files or on function symbols in the DLL.
  9. From the Build menu, click Start Debug and Go to start the debugger.

To debug a DLL created with an external project

  1. From the Project menu, click Settings.

    The Project Settings dialog box appears.

  2. Choose the Debug tab.
  3. In the Category drop-down list box, select General.
  4. In the Executable For Debug Session text box, type the name of the DLL that your external makefile builds.
  5. Click OK to store the information in your project.
  6. Build a debug version of the DLL with symbolic debugging information, if you don’t already have one.
  7. Follow one of the two procedures immediately preceding this one to debug the DLL.

See Also

Debugging DLLs


How Can I Tell Which DLL My Program Crashed In?

Full Problem Description: My application crashes during a call to a system DLL or someone else’s code. I’m not sure which DLL was active when the crash occurred. How can I find out?

If you experience a crash in a DLL outside your own program, you can identify the location using the new Module List dialog box.

To find where a crash occurred using the Module List dialog box

  1. Note the address where the crash occurred.
  2. From the Debug menu, click Modules. The Module List dialog box appears.

    The Modules List dialog box has four columns: Module, Address, Path, and Order (which tells you the order in which modules are loaded). You may need to use the scroll bar to see the fourth column. There is a button at the top of each column. DLLs are initially sorted by load order.

  3. Click the Address button to sort the DLLs by address.
  4. Scan through the sorted list to find the DLL whose address range contains the address where the crash occurred.
  5. Note the DLL name and path for future reference.

See Also

Debugging Technique FAQs


Why Don't My DLL Breakpoints Work?

Some reasons why your breakpoints don’t work as expected are listed here, along with solutions or work-arounds for each. If you follow the instructions in one topic and are still having breakpoint problems, look at some of the other topics. Often breakpoint problems result from a combination of conditions.

  1. You can't set a breakpoint in a source file when the corresponding symbolic information isn't loaded into memory by the debugger.

    You cannot set a breakpoint in any source file when the corresponding symbolic information will not be loaded into memory by the debugger. Symptoms include messages such as "the breakpoint cannot be set" or a simple, noninformational beep.

    When setting breakpoints before the code to be debugged has been started, the debugger uses a breakpoint list to keep track of how and where to set breakpoints. When you actually begin the debugging session, the debugger loads the symbolic information for all the code to be debugged and then walks through its breakpoint list, attempting to set the breakpoints.

    However, if one or more of the code modules have not been designated to the debugger, there will be no symbolic information for the debugger to use when walking through its breakpoint list. Situations where this is likely to occur include:

    • Attempts to set breakpoints in a DLL before the call to LoadLibrary.
    • Setting a breakpoint in an ActiveX server before the container has started the server.
    • Other similar cases.

    To prevent this behavior in Visual C++, specify all additional DLLs and COM servers in the Additional DLLs field in the Debug/Options dialog box to notify the debugger that you want it to load symbolic debug information for additional .DLL files. When this has been done, breakpoints set in code that has not yet been loaded into memory will be "virtual" breakpoints. When the code is actually loaded into memory by the loader, these become physical breakpoints. Make sure that these additional debugging processes are not already running when you start your debugging session. The debugging process and these additional processes must be synchronized at the same beginning point to work correctly, hitting all breakpoints.

  2. Breakpoints are missed when more than one copy of a DLL is on your hard disk.

    Having more than one copy of a DLL on your hard drive, especially if it is in your Windows directory, can cause debugger confusion. The debugger will load the symbolic information for the DLL specified to it at run time (with the Additional DLLs field in the Debug/Options dialog box), while Windows has actually loaded a different copy of the DLL itself into memory. Because there is no way to force the debugger to load a specific DLL, it is a good idea to keep only one version of a DLL at a time in your path, current directory, and Windows directory.

  3. You can’t set "Break When Expression Has Changed" breakpoints on a variable local to a DLL.

Setting a "Break When Expression Has Changed" breakpoint on a variable local to a DLL function before the call to LoadLibrary causes the breakpoint to be virtual (there are no physical addresses for the DLL in memory yet). Virtual breakpoints involving expressions pose a special problem. The DLL must be specified to the debugger at startup (causing its symbolic information to be loaded). In addition, the DLL's executable code must also be loaded into memory before this kind of breakpoint can be set. This means that the calling application's code must be executed to the point after its call to LoadLibrary before the debugger will allow this type of breakpoint to be set.

See Also

Debugging DLLs


Can I Debug a .DLL Without a Project or Workspace?

Yes, you can debug a .DLL without a project or workspace. For example, maybe you just picked up a .DLL and the related source code but you don’t have an associated project or workspace. You can use the Open command on the File menu to select the .DLL file you want to debug. The debug information should already be in either the .DLL or the related .PDB file. After Visual C++ opens the file, choose the Start Debug command on the Build menu to begin debugging.

Note You can also select the .DLL file you want to debug using the Open Workspace command on the File menu. Both the Open and the Open Workspace command work the same way.
Note When you open a file, the Executable for debug session edit box on the Debug tab of the Project Settings dialog is automatically set to the name of the file that is opened. You must specify the name of the .EXE file to use with this .DLL. When you close the temporary workspace, you can optionally save the project settings in a <project>.opt file.

See Also

Debugging Technique FAQs


Expressions in the Debugger

This section describes the syntax used by expressions in the debugger. These expressions include:

  • C/C++ expressions
  • Assembly-language expressions
  • C# expressions
  • Visual Basic expressions
  • Script expressions
  • SQL expressions

In addition, it covers two special syntax elements that can be used when specifying expressions in the debugger:

  • The Context Operator
  • Format Specifiers

See Also

Debugging Your Program


C/C++ Expressions in the Debugger

The debugger accepts most Microsoft and ANSI C/C++ expressions. There are some operator functions, unsupported C/C++ operators, additional operators, restrictions on C/C++ expressions, and restrictions and additions on C++ expressions in the debugger of which you should be aware.

See Also

Expressions in the Debugger


Unsupported Operators

Debugger expressions do not support the following operators:

  • , (comma)
  • ?:
  • .*
  • ->*
  • ::*

See Also

C/C++ Expressions in the Debugger


Additional Operators

Debugger expressions support the following additional operators:

  • The context operator ({ }) to specify the context of a symbol.
  • Memory operators (BY, WO, and DW) to access memory. Memory operators have the lowest precedence of any operator.

The memory operators are useful mainly in debugging assembly-language code.

The Context Operator

The context operator ({ }) is not part of the C/C++ language. It is specific to the debugger. The context operator specifies the context of an expression or line number that appears in more than one place in the source code.

For example, you can use the context operator to specify a name in an outer scope that is otherwise hidden by a local name.

When a debugger expression that contains a symbol, the expression evaluator searches for the symbol in the following order:

  1. Lexical scope outward. Starting with the current block (series of statements enclosed in curly braces) and continuing outward with the enclosing block. The current block is the code containing the current location (instruction pointer address).
  2. Function scope. The current function.
  3. Class scope, if the current location is inside a C++ member function. Class scope includes all base classes. The expression evaluator uses the normal dominance rules.
  4. Current module.
  5. Global symbols.
  6. Other modules.
  7. Public symbols in the program.

With the context operator, you specify the starting point of the search and bypass the current location. You cannot specify a block because a block has no name. You cannot specify a class, but you can specify a member function of the class and let the expression evaluator search outward.

Syntax

{[function],[file],[image]} [expression]
function
The name of a function in the program.
file
The name of a source file. You must specify a source file if the function is outside the current scope. If the file is not in the current directory, you must specify the path.
expression
The path of a program's DLL or .exe file.
object
A line number or symbol.

The context operator has the same precedence and associativity as the type-cast operator. You can omit function, file, or expression, but you must specify all leading commas. If a name contains a comma, you must enclose the name in parentheses.

Example

Suppose you want to display the value of the variable Pos, which is local to the function make_box defined in the source file DRAWBOX.C. Type the following in the QuickWatch dialog box or the Watch window:

{make_box,C:\TREE1\DRAWBOX.C,C:\TREE2\DISPTXT.DLL}Pos

If there is more than one source file called DRAWBOX.C, the third parameter specifies that the source file containing the function make_box is the one used by DISPTXT.DLL. Otherwise, you can leave out this parameter.

See Also

C/C++ Expressions in the Debugger


Restrictions on C/C++ Expressions

When you enter a C/C++ expression in a debugger window, these general restrictions apply:

  • A debugger expression cannot call an intrinsic or inlined function unless the function appears at least once as a normal function.
  • Debugger expressions limit pointer type cases to one level of indirection. You can use (char *)sym, for example, but not (char **)sym or char far *( far *).
  • If you cast to a type, the type must be known to the debugger. You must have another object of that type in your program. Types created using typedef statements are not supported.
  • In debugger expressions, the C++ scope operator (::) has lower precedence than it does in source code. In C++ source, this operator has the highest precedence. In the debugger, its precedence falls between the base and postfix operators (->, ++, --) and the unary operators (!, &, *, and others).
  • Other differences and restrictions concern:
  • Numeric constants
  • String literals
  • Symbol formats

Finally, there are some differences and restrictions specific to C++ expressions. For more information on these special considerations, see C++ Expressions.

Numeric Constants

Debugger expressions can use integer constants in octal, hexadecimal, or decimal format. By default, the debugger expects decimal constants. You can change this to hexadecimal: on the Tools menu, click Options. In the Options dialog box, select the Hexadecimal display check box on the Debug tab.

You can use prefix or suffix symbols to represent numbers in another base. The following table shows the forms you can use.

Syntax | Base
digits | Decimal or hexadecimal, as selected in the Options dialog box on the Debug tab (decimal by default).
0digits | Octal (base 8)
0ndigits | Decimal (base 10)
0xdigits | Hexadecimal (base 16)
digitsh | Hexadecimal (base 16)

If you select hexadecimal display in the Options dialog box, you can enter hexadecimal values without the hexadecimal prefix. In that mode, some hexadecimal values (such as abc) can be interpreted as either values or symbols. The debugger looks for a symbol with the matching name first. To enter a number whose hexadecimal representation is the same as a symbol in the program, you must use the hexadecimal prefix (0xabc, for example).

String Literals

Syntax

"string"

The debugger accepts string expressions in C format. You can use any ANSI C escape sequences within a string. (For example, \" for a double quote within a string.)

A string specified in the debugger is volatile. You cannot rely on its continued existence. This means that you cannot assign a string (such as "hello") to a character pointer variable (such as pChar).

You can, however, change a pointer to refer to a different string in your program.

Symbol Formats

You enter a debugger expression that contains symbols in the same form used in the source code, provided the symbols are in a module compiled with full debug information (/Zi or /ZI). If you enter an expression that contains public symbols (symbols found in libraries or in modules compiled with /Zd or /CO), you must use the decorated name of the symbol (the form found used in the object code).

You can get a listing of all names in their decorated and undecorated forms using the LINK /MAP option.

Name decoration is the mechanism used to enforce type-safe linkage. This means that only the names and references with precisely matching spelling, case, calling convention, and type are linked together.

Names declared with the C calling convention (either implicitly or explicitly using the _cdecl keyword) begin with an underscore ( _ ). For example, the function main can be displayed as _main. Names declared as _fastcall begin with the @ symbol.

For C++, the decorated name encodes the type of the symbol in addition to the calling convention. This form of the name can be long and difficult to read. The name begins with at least one question mark (?). For C++ functions, the decoration includes the function's scope, the types of the function's parameters, and the function's return type.

See Also

C/C++ Expressions in the Debugger


Restrictions and Additions on C++ Expressions in the Debugger

The C++ expression evaluator accepts almost all C++ expressions, with some restrictions and some additions. This section describes these special considerations.

  • Access control
  • Ambiguous references
  • Inheritance
  • Constructors, destructors, and conversions
  • Operator functions
  • Overloading

Access Control

The debugger can access all class members regardless of access control. You can examine any member of a class object including base classes and embedded member objects.

Ambiguous References

If a debugger expression refers to an ambiguous member name, you must use the class name to qualify it. For example, if CObject is an instance of CClass, which inherits member functions named expense from both AClass and BClass, CObject.expense is ambiguous. You can resolve the ambiguity like this:

CObject.BClass::expense

To resolve ambiguities, the expression evaluator applies normal dominance rules regarding member names.

Inheritance

When you use the debugger to display a class object that has virtual base classes, the members of the virtual base class are displayed for each inheritance path, even though only one instance of those members is stored. You can access members of an object through a pointer to the object, and you can call virtual functions through a pointer.

For example, assume the class CEmployee defines a virtual function computePay, which is redefined in a class that inherits from CEmployee. You can call computePay through a pointer to CEmployee and have the proper function executed:

empPtr->computePay()

You can cast a pointer to a derived class object into a pointer to a base class object. The reverse cast is not permitted.

Constructors, Destructors, and Conversions

You cannot call a constructor or destructor for an object, either explicitly or implicitly, using an expression that calls for construction of a temporary object. For example, the following expression explicitly calls a constructor and results in an error message:

Date( 2, 3, 1985 )

You cannot call a conversion function if the destination of the conversion is a class. Such a conversion involves the construction of an object. For example, if myFraction is an instance of CFraction, which defines the conversion function operator FixedPoint, the following expression results in an error:

(FixedPoint)myFraction

However, you can call a conversion function if the destination of the conversion is a built-in type. If CFraction defines a conversion function operator float, the following expression is legal in the debugger:

(float)myFraction

You can call functions that return an object or declare local objects.

You cannot call the new or delete operators. This expression does not work in the debugger:

new Date(2,3,1985)

Overloading

A debugger expression can call overloaded functions if an exact match exists or if a match does not require a conversion involving object construction. For example, if the calc function takes a CFraction object as a parameter, and the CFraction class defines a single-argument constructor that accepts an integer, the following expression results in an error:

calc( 23 )

Even though a legal conversion exists to convert the integer into the CFraction object calc expects, such a conversion involves the creation of an object and is not supported.

See Also

C/C++ Expressions in the Debugger


Operator Functions

A debugger expression can invoke operator functions for a class implicitly or explicitly. For example, suppose myFraction and yourFraction are instances of a class that defines operator+. You can display the sum of those two objects using this expression:

myFraction + yourFraction

It can also call an operator function using the functional notation:

myFraction.operator+( yourFraction )

If an operator function is defined as a friend, you can call it implicitly using the same syntax as for a member function, or you can invoke it explicitly, as follows:

operator+( myFraction, yourFraction )

Like ordinary functions, operator functions cannot be called with arguments that require a conversion involving object construction.

See Also

C/C++ Expressions in the Debugger


Assembly-Language Expressions in the Debugger

The debugger can correctly evaluate assembly-language expressions, with some restrictions. The syntax used for some assembly-language expressions differs from the syntax used in assembly-language development systems such as MASM.

The following topics cover debugger expression syntax for:

  • Memory operators
  • Register indirect addressing
  • Register indirect with displacement
  • Address of a variable
  • PTR operator
  • Strings
  • Array and structure elements
  • Context Operator

See Also

Expressions in the Debugger


Memory Operators

Memory operators are unary operators that return the result of a direct memory operation. These operators are used mainly to debug assembly-language code.

Syntax

{BY | WO | DW} address

The BY operator returns a short integer that contains the first byte at address. This operator simulates BYTE PTR.

The WO operator returns a short integer that contains the value of the word (two bytes) at address. This operator simulates the Microsoft Macro Assembler WORD PTR operation. The DW operator returns a long integer that contains the value of the first four bytes at address. This operator simulates DWORD PTR.

The x format specifier used in some of these examples causes the result to be displayed in hexadecimal.

Examples

  • To display the first byte at the address of the variable sum:
    BY sum
  • To display the first word at the address of the variable new_set:
    WO new_set
  • To display the doubleword at the address of sum:
    DW sum
  • To display the byte pointed to by the EBP register with a displacement of 6:
    BY ebp+6,x
  • To display the word pointed to by the stack pointer (the last word pushed onto the stack):
    WO esp,x
  • To display the doubleword pointed to by the ESI register:
    DW esi,x

See Also

Assembly-Language Expressions


Register Indirect

The debugger does not recognize brackets ([ ]) to indicate a memory location pointed to by a register. Instead, use the BY, WO, and DW operators to reference the corresponding byte, word, or doubleword values.

MASM expression | Debugger expression | C++ expression
BYTE PTR [bx] | BY ebx | *(unsigned char) ebx
WORD PTR [bp] | WO ebp | *(unsigned short *) ebp
DWORD PTR [bp] | DW ebp | *(unsigned long *) ebp

See Also

Assembly-Language Expressions


Register Indirect with Displacement

To perform based, indexed, or based-indexed indirect mode operations with a displacement, use the BY, WO, and DW operators with addition.

MASM expression | Debugger expression
BYTE PTR [edi+6] | BY edi+6
BYTE PTR Test[ebx] | BY &Test+ebx
WORD PTR [esi][ebp+6] | WO esi+ebp+6
DWORD PTR [ebx][esi] | DW ebx+esi

See Also

Assembly-Language Expressions


Address of a Variable

Use the C address-of operator (&) instead of the MASM OFFSET operator.

MASM expression | Debugger expression
OFFSET Var | &Var

See Also

Assembly-Language Expressions


PTR Operator

Use type casts or the BY, WO, and DW operators with the address-of operator (&) to replace the assembly-language PTR operator.

MASM expression | Debugger expression
BYTE PTR Var | BY &Var
*(unsigned char*) | &Var
WORD PTR Var | WO &Var
DWORD PTR Var | DW &Var
*(unsigned long*) | &Var

See Also

Assembly-Language Expressions


Assembly-Language Strings

Add the string format specifier ,s after the variable name.

MASM expression | Debugger expression
String | String,s

Because C strings end with a null (ASCII 0) character, the debugger displays all characters from the first byte of the variable up to the next null byte in memory when you request a string display. If you intend to debug an assembly-language program, and you want to view strings in the Watch window, you should delimit string variables with a null character. You can view null-terminated or unterminated strings in the Memory window.

See Also

Assembly-Language Expressions


Array and Structure Elements

Prefix an array name with the address-of operator (&) and add the desired offset. The offset can be an expression, number, register name, or variable.

The following examples show how to do this for byte, word, and doubleword arrays.

MASM expression | Debugger expression
String[12] | BY &String+12*(&String+12)
aWords[bx+di] | WO &aWords+bx+di*(unsigned*)(&aWords+bx+di)
aDWords[bx+4] | DW &aDWords+bx+4*(unsigned long*)(&aDWords+bx+4)

See Also

Assembly-Language Expressions


Context Operator

The context operator qualifies a breakpoint location, variable name, or expression, as shown here:

  • {[function],[source],[module] } location
  • {[function],[source],[ module] } variable_name
  • {[function],[source],[ module] } expression
  • {[function],[source],[ module] } class::*

The curly braces can contain any combination of function name, source file pathname, and module (executable or DLL) pathname.

Example

To set a breakpoint at line 301 of EXAMPLE.CPP:

{,EXAMPLE.CPP,}@301

If you omit either function or module, the two commas cannot be omitted. As a result, the following syntax is illegal:

{File.c, File.exe} @143 — Bad

If you omit both source and module, however, you can omit the commas. The following syntax is legal:

{Fun} @143

If the source or module pathname includes a comma, an embedded space, or a brace, you must use quotation marks around the pathname so that the context parser can properly recognize the string. Single quotation marks are considered to be part of a Windows NT/95/98 filename, so you must use double quotation marks. For example,

{,"a long, long, name.c", } .143

See Also

Assembly-Language Expressions


NGWS SDK Documentation

This is preliminary documentation and subject to change.
To comment on this topic, please send us email at ngwssdk@microsoft.com. Thanks!

Visual Basic Expressions in the Debugger

Text to come.

See Also

Expressions in the Debugger


NGWS SDK Documentation

This is preliminary documentation and subject to change.
To comment on this topic, please send us email at ngwssdk@microsoft.com. Thanks!

SQL Expressions In the Debugger

Text to come.

See Also

Expressions in the Debugger


NGWS SDK Documentation

This is preliminary documentation and subject to change.
To comment on this topic, please send us email at ngwssdk@microsoft.com. Thanks!

Script Expressions In The Debugger

Text to come.

See Also

Expressions in the Debugger


NGWS SDK Documentation

This is preliminary documentation and subject to change.
To comment on this topic, please send us email at ngwssdk@microsoft.com. Thanks!

C# Expressions in the Debugger

Text to come.

See Also

Expressions in the Debugger


Format Specifiers

You can use format specifiers to change the display of values when you view variables or expressions in the Watch window or QuickWatch dialog box.

To use a format specifier, type the expression, followed by a comma, followed by the appropriate specifier.

Example

Suppose nVar is an integer variable, and the Watch window shows that it contains the value 0x0065. Suppose you want to see value expressed as a character instead of an integer. In the Name column, after the variable name, you would add the character format specifier, c:

nVar,c

Instead of the integer value 0x0065, the Value column now displays the character value, 'e'.

If you want to apply a format specifier to elements of an array or members of an object, you must apply it directly to each element or member. You cannot apply it to the array or object as a whole. For example, suppose you had an array nArray and wanted to see the first four elements in character format. You would enter these expressions in the Watch window:

nArray[0],c
nArray[1],c
nArray[2],c
nArray[3],c

The following tables show the format specifiers recognized by the debugger.

Specifier | Format | Value | Displays
d,i | signed decimal integer | 0xF000F065 | -268373915
u | unsigned decimal integer | 0x0065 | 101
o | unsigned octal integer | 0xF065 | 0170145
x,X | Hexadecimal integer | 61541 (decimal) | 0x0000F065
l,h | long or short prefix for: d, i, u, o, x, X | 00406042,hx | 0x0c22
f | signed floating point | 3./2. | 1.500000
e | signed scientific notation | 3./2. | 1.500000e+000
g | signed floating point or signed scientific notation, whichever is shorter | 3./2. | 1.5
c | Single character | 0x0065 | 'e'
s | String | 0x0012fde8 | "Hello world"
su | Unicode string |  | "Hello world"
st | Unicode string or ANSI string, depending on Unicode Strings setting in autoexp.dat. |  |
hr | HRESULT or Win32 error code. (The debugger now decodes HRESULTs automatically, so this specifier is not required in those cases. It is not possible to decode HRESULTs if you compile with /noHRESULT.) | 0x00000000L | S_OK
wc | Window class flag. | 0x00000040 | WC_DEFAULTCHAR
wm | Windows message numbers | 0x0010 | WM_CLOSE

The following table contains formatting symbols used for memory locations.

Symbol | Format | Displays
ma | 64 ASCII characters | 0x0012ffac .4...0...".0W&.......1W&.0.:W..1...."..1.JO&.1.2.."..1...0y....1
m | 16 bytes in hexadecimal, followed by 16 ASCII characters | 0x0012ffac B3 34 CB 00 84 30 94 80 FF 22 8A 30 57 26 00 00 .4...0...".0W&..
mb | 16 bytes in hexadecimal, followed by 16 ASCII characters | 0x0012ffac B3 34 CB 00 84 30 94 80 FF 22 8A 30 57 26 00 00 .4...0...".0W&..
mw | 8 words | 0x0012ffac 34B3 00CB 3084 8094 22FF 308A 2657 0000
md | 4 doublewords | 0x0012ffac 00CB34B3 80943084 308A22FF 00002657
mq | 4 quadwords | 0x0012ffac 7ffdf00000000000 5f441a790012fdd4
mu | 2-byte characters (Unicode) | 0x0012fc60 8478 77f4 ffff ffff 0000 0000 0000 0000

You can use a memory location specifier with any value or expression that evaluates to a location.

Format Specifiers for Unicode Strings

To display a Unicode string, use the su format specifier. To display data bytes for Unicode characters, use the mu format specifier.

Special Specifier for Strings

There is one special format specifier you can use to display a character array as a string. This specifier is ampersand (&). It is special because, unlike other specifiers, you use it as a prefix rather than a suffix and there is no comma between the specifier and the variable name:

&CharArray

See Also

Expressions in the Debugger


Debugging Preparation

The debugging functions built into the development environment enable you to test your Visual C++, Visual Basic, and mixed language programs. You can set and manage breakpoints, view and alter variables, and control threads. During the debugging process, you can halt to examine the state of an executable program, a dynamic-link library (DLL), threads, or an ActiveX control at nearly any point during program execution.

Debugging is a two-step process. First, you correct compile-time errors that prevent you from building your project, such as incorrect syntax, misspelled keywords, or type mismatches. Then, you use the debugger to detect and correct logic errors and errors in sequencing, branching, and interaction among program components.

This section covers the following topics:

  • Debug Build Versus Release Build
  • Changing Project Settings for a Debug Build
  • What Are .PDB and .DBG Files?
  • Debugging Optimized Code
  • Enabling the Debugging Features
  • Enabling Just-in-Time Debugging

See Also

Debugging Your Program


Debug Build Versus Release Build

Visual Studio projects can have separate configurations for Release and Debug versions. Visual Studio creates these versions, with appropriate default settings, automatically when you create a project. You can change the project settings in the Project Property Pages dialog box. (Select the project in the Solution Explorer, then choose Property Pages from the View menu).

Version | Default Values
Debug | Full symbolic debugging information in Microsoft format No optimization (optimization generally makes debugging more difficult)
Release | No symbolic debugging information Optimized for maximum speed

You can change the debug default options, for example, to output line numbers only, to generate a mapfile, or to redirect output.

See Also

Debugging Preparation


Changing Project Settings for a Debug Build

When you create a Visual C++ project, a Release and a Debug version of the project files are automatically made. You can change the project settings in the C/C++ tab of the Project Settings dialog (from the Settings command on the Project menu).

Option | Result
Program Database (default) | Produces a program database (.pdb) containing type information and symbolic debugging information.
Line Numbers Only | Produces an .obj file or executable (.exe) file containing only global and external symbol and line-number information (no symbolic debugging information).
C7 Compatible | Produces an .obj file and an .exe file containing line numbers and full symbolic debugging information for use with the debugger.
None | Produces no debugging information.

For more information, see What Are .pdb and .dbg Files?.

To change the debug information generated during a build

  1. In the Solution Explorer, select the project.
  2. From the View menu, click Property Pages.

    The Project Property Pages dialog box appears.

  3. Choose the Configuation Settings folder.
  4. Choose the Build or Debug folder.
  5. Edit the properties in the properties grid.
  6. Click OK.

To change the format of the debug information generated during a build

  1. From the Project menu, click Settings.

    The Project Settings dialog box appears.

  2. Choose the Link tab.
  3. Choose General from the Category dropdown list.
  4. Choose Generate debug info.
  5. The default format is Microsoft Format (/DEBUGTYPE:CV). To change the format to COFF, type /DEBUGTYPE:COFF in the Project Options text box.
  6. Click OK to set the option and close the Project Settings dialog box.

To generate a mapfile during a build

  1. From the Project menu, click Settings.

    The Project Settings dialog box appears.

  2. Choose the Link tab.
  3. Choose Debug from the Category dropdown list.
  4. Select the Generate mapfile check box.
  5. Enter a name in the Mapfile name text box or accept the default.
  6. Click OK to accept the settings option and close the Project Settings dialog box.

To redirect input/output in a Win32 Debug build

  1. From the Project menu, click Settings.

    The Project Settings dialog box appears.

  2. Select the Debug tab.
  3. In the Program Arguments text box, specify one or more I/O redirection commands from the following table. You can combine I/O redirection commands in any order.
  4. Click OK to accept the redirection and close the Project Settings dialog box.
Command | Action
<file | Reads stdin from file (see Note below)
>file | Sends stdout to file (see Note below)
>>file | Appends stdout to file (see Note below)
2>file | Sends stderr to file (see Note below)
2>>file | Appends stderr to file
2>&1 | Sends stderr (2) output to same location as stdout (1)
1>&2 | Sends stdout (1) output to same location as stderr (2)
Note You can use the >, <, >>, and 2> commands for applications that read or write to stderr and stdout. In most (if not all) cases, this is specific to console applications.

See Also

Debugging Preparation


What are .pdb And .dbg Files?

This section covers the following topics:

  • The .pdb Files
  • The .dbg Files

See Also

Debugging Preparation


The .pdb Files

The .pdb (program database) file holds debugging and project state information. The .pdb file provides the information needed for incremental linking of debug program versions.

Although earlier, 16-bit versions of Visual C++ used .pdb files, the debugging information stored in them was appended to the end of the .exe or .DLL file by the linker. Now, with 32-bit .exe’s, both the linker and the integrated debugger allow .pdb files to be used directly during the debugging process, eliminating substantial amounts of work for the linker and bypassing the cumbersome CVPACK limit of 64K types.

By default, when you build projects generated by Visual C++, the compiler switch /Fd is used to rename the .pdb file to <project>.pdb. Therefore, you will have only one .pdb file for the entire project.

When you run makefiles that were not generated by Visual C++, and the /Fd is not used with /Zi, you will end up with two .pdb files:

  • VCx0.pdb (where x refers to the major version of the corresponding Visual C++). This file stores all debugging information for the individual .obj files and resides in the directory of the project makefile.
  • <project>.pdb This file stores all debugging information for the resulting .exe file and resides in the \WINDEBUG subdirectory.

Why two files? When the compiler is run, it doesn't know the name of the .exe file into which the .obj files will be linked, so the compiler can't insert the information into <project>.pdb. The two files store different information. Each time you compile an .obj file, the compiler merges the debugging information into VCx0.pdb. It only inserts information concerning types and does not insert symbol information such as function definitions. One benefit of this is that when every source file includes common header files such as <windows.h>, all the typedefs from these headers are only stored once, rather than in every .obj file.

When you run the linker, it creates <project>.pdb, which holds the debugging information for the project's .exe file. All debugging information, including function prototypes and everything else, is placed into <project>.pdb, not just the type information found in VCx0.pdb. The two kinds of .pdb files share the same extension because they are architecturally similar and they both allow incremental updates. Nevertheless, they actually store different information.

The Visual C++ debugger uses the <project>.pdb file created by the linker directly, and embeds the absolute path to the .pdb in the .exe or .dll file. If the debugger can't find the .pdb file at that location or if the path is invalid (for example, if the project was moved to another computer), the debugger looks for it in the current directory.

See Also

What are .pdb And .dbg Files?


The .dbg Files

The .dbg (debug) files created with the 32-bit NT toolset are in the Portable Executable (PE) file format. They contain sections with COFF, FPO, and in some cases CodeView information. The Visual C++ integrated debugger can read .dbg files in this format, but it ignores the COFF symbol sections and looks only for CodeView information.

The Visual C++ integrated debugger can also use .dbg files as long as they are made from a binary containing CodeView format debugging output. These are useful for debugging when the source code is not available. Even without the source, .dbg files allow you to set breakpoints on functions, watch variables, and see the functions in the callstack. They are also required for OLE RPC debugging.

Tip When working with symbols from a .dbg file, you must use the fully decorated names. For example, to set a breakpoint on a call to the Windows sndPlaySound function, you would specify _sndPlaySoundA@8 as the location.

The earlier, 16-bit version of the Visual C++ .dbg file format was constrained by the 64K limit for a .com file. The symbolic information was therefore inserted into a separate .dbg file, which had only CodeView information in it. The .dbg files could also be generated by running CVPACK on an .exe file using the /strip option.

For 32-bit .exe's, Visual C++ reads the format used in the Windows NT .dbg files (supplied for use with its system .dll files). These .dbg files are in the Portable Executable (PE) file format and contain sections with COFF, FPO, and in some cases CodeView symbolic information. The Visual C++ debugger reads .dbg files in this format only. Furthermore, it only uses the CodeView information, ignoring the other symbol sections.

It is possible to strip debug information from a PE file and store it in a .dbg file for use by debuggers. For this to work, the debugger needs to know whether to find the debug information in a separate file or not and whether the information has been stripped from the file or not. One method would be for the debugger to search through the executable file looking for debug information. However, to save the debugger from having to search the file, a file characteristic field (IMAGE_FILE_DEBUG_STRIPPED) indicates that the file has been stripped. Debuggers can look for this field in the PE file header to quickly determine if the debug information is present in the file.

To generate a .dbg file in this format, you can use REBASE.EXE, which is provided with the Platform SDK. Please see the Platform SDK documentation for more details.

During the Windows NT retail builds, debug symbols are stripped from the system binaries and drivers and stored in separate .dbg files. This is done because the Windows NT kernel debugger can use these .dbg files and provide debugging symbols even for optimized drivers. Remember, however, that the Visual C++ integrated debugger is not designed to debug protected mode kernel code.

The Windows NT symbol files can be found in a debug subdirectory of the \SUPPORT directory on the Windows NT retail compact disc. These files must be copied from the compact disc to your hard drive. For user mode debugging on the target debugger machine, .dbg symbols must be present in the Windows NT \<winnt>\SYMBOLS directory of the target system (<winnt> is the directory where Windows NT is installed). The Visual C++ setup program installs an "NT System Symbols Setup" icon in your program group. You can use it to automatically copy the .dbg files from your Windows NT compact disc to the correct directory structure on your hard drive.

For kernel debugging, place .dbg files into a symbols tree underneath the directory specified by the _NT_SYMBOL_PATH environment variable (for example, C:\DEBUG\SYMBOLS). Kernel debugging is possible with a minimal set of symbols consisting of symbols for all the drivers (*.sys) in the SYMBOLS\SYS directory, and symbols for NTOSKRNL.EXE and HAL.DLL in the SYMBOLS\EXE and SYMBOLS\DLL directories, respectively.

For more information, refer to the discussion regarding kernel debugging in the Windows NT DDK Programmer's Guide.

See Also

What are .pdb And .dbg Files?


Debugging Optimized Code

During optimization, the compiler repositions and reorganizes instructions derived from your source code, resulting in more efficient execution of the program. Because the information in the optimized code has been rearranged, the debugger cannot always identify the source code that corresponds to a set of instructions. For this reason, it is advisable to debug your code before optimizing it whenever possible. You can enable optimization after you finish debugging.

Following are instructions for preventing optimization and suggestions for debugging optimized code, if necessary.

To prevent the compiler from optimizing code

  • When you create a new project, select the Win32 Debug target. Build and debug the Win32 Debug target until you are ready to build a Win32 Release target. The compiler does not optimize the Win32 Debug target.

    – or –

  • Use the /Od compiler option on the command line, and remove any other /O? compiler options.

    – or –

  1. From the Project menu, click Settings.

    The Project Settings dialog box appears.

  2. Select the C/C++ tab.
  3. In the Optimizations drop-down list box, select Disable (Debug).

You can enable optimizations after you finish debugging.

Debugging optimized code

Some bugs affect optimized code but do not affect unoptimized code. If you must debug optimized code, use the following techniques:

  • Use the /Zi compiler option to get maximum symbolic information for your program.
  • Use the Disassembly Window and Registers Window. Set breakpoints at the appropriate locations using the Disassembly window.

To see why the Disassembly window is useful, consider the following example:

for (x=0; x<10; x++)

Suppose you set a breakpoint at this line. You might expect the breakpoint to be hit 10 times. But if this code is optimized, the breakpoint is hit only once, because the compiler recognizes that the first instruction associated with this line, which assigns the value of 0 to x, needs to execute only once. The compiler moves this instruction out of the loop. If you set a breakpoint on this source-code line, the debugger sets the breakpoint on the first instruction, which executes only once.

The instructions that compare and increment x remain inside the loop. To set a breakpoint on these instructions, use the Disassembly Window. By viewing the object code the source-code line creates, you can set a breakpoint at the appropriate instruction. You can set a breakpoint at the location where the condition is checked or the variable is incremented. You can use the Step Into or Step Over commands in the Disassembly window to step by assembly instructions, which allows greater control than stepping by source-code line.

See Also

Debugging Preparation


Enabling the Debugging Features

Debugging is enabled when your program is compiled with the symbol _DEBUG defined. This is typically done by passing the /D_DEBUG flag on the compiler command line. When you define the _DEBUG symbol, sections of code delimited by #ifdef _DEBUG / #endif are compiled.

You also must link with the debug versions of MFC libraries. Setting the Win32 Debug option in Visual C++ ensures linking with the debug libraries. The debug versions of the library have a “D” at the end of the library name. The static debug version of MFC is named NAFXCWD.lib, and the static release version (nondebug) is named NAFXCW.lib. The DLL debug version of MFC is named MFCvvD.lib, and the DLL release version (nondebug) is named MFCvv.lib (where vv is the version number).

To enable the debugging features

  • Choose the Win32 Debug target in the Select Active Configuration box on the Build toolbar.

See Also

Debugging Preparation


Enabling Just-in-Time Debugging

With Just-in-time debugging, you can run a program outside Visual C++. When an application error occurs, it calls the Visual C++ debugger.

To enable Just-in-time debugging

  1. From the Tools menu, click Options.
  2. In the Options dialog box, select the Debugging folder.
  3. Under Just-In-Time Debugging, select the On This Machine button.

    The Debugger Properties dialog box appears.

  4. In the Program Types box, select the program type (for example, Win32 or NGWS runtime) that you want to debug.
  5. Select the Enable JIT Debugging and Enable Ettach checkboxes.
  6. Click OK to dismiss the Debugger Properties dialog box.
  7. Click OK to dismiss the Options dialog box.
Note If you are running Windows NT, you must have administrator privileges to set the Just-in-time debugging option.

See Also

Debugging Preparation


Debugging UI Reference

The following table shows the windows and dialog boxes you can use for debugging your application.

  • Attach To Process dialog box
  • Locals window
  • Autos window
  • Memory window
  • Breakpoint Condition dialog box
  • Modules window
  • Breakpoint Hit Count dialog box
  • New Breakpoint dialog box
  • Breakpoint Properties dialog box
  • Programs dialog box
  • Breakpoints window
  • QuickWatch dialog box
  • Call Stack window
  • Registers window
  • Debugger Properties On <Machine> dialog box
  • Running Documents window
  • Disassembly window
  • This window
  • Exceptions dialog box
  • Threads window
  • Find Exception dialog box
  • Watch window

See Also

Debugging Your Program


Attach To Process Dialog Box

The Attach to Process dialog box opens when you select a program from the Available Processes box in the Programs dialog box and choose Attach.

Process
The path name for the executable from which the process was created.
Choose Program Types...
In this box, select or clear the check boxes next to the program types you want to be able to attach to for debugging.
All
Choose this button to enable attaching to all program types.
None
Choose this button to disable attaching to any program type.
Existing programs that will be debugged...
This box shows all program types that are currently running and available for debugging based on the types chosen in Choose Program Types.
OK
Attach to the program shown in the Process box.
Cancel
Just call the whole thing off.

See Also

Attaching To a Running Program or Multiple Programs | Debugging UI Reference


Autos Window

To open the Breakpoints window, you must be debugging. From the Debug menu, choose Windows, and then choose Breakpoints.

To save screen space, the Autos window shares the same frame as the Breakpoints, Locals, This, and Disassembly windows. You can switch back and forth between these windows using the tabs at the bottom of the frame. The title bar changes accordingly.

The Autos window contains the following information:

Name
The names of all variables in the current statement and the previous statement. The current statement is the statement at the current execution location, which is the statement that will be executed next if execution continues. Structure and array variables have a tree control that you can use to show or hide the elements.
Value
The value contained by each variable. By default, integer variables are represented in decimal form. You can change the representation to hexadecimal in the Tools dialog box or by right-clicking on the Autos window and choosing the Hexadecimal Display option from the shortcut menu.
Type
The data type of each variable listed in the Name column.

See Also

Using the Autos Window | Debugging UI Reference


Breakpoint Condition Dialog Box

The Breakpoint Condition dialog box opens when you select the Condition button from a New Breakpoint or Breakpoint Properties dialog box.

Use the Breakpoint Condition dialog box to attach a condition to a breakpoint, or to remove or change a condition previously attached. The condition can be any valid expression accepted by the debugger. The evaluation of this expression determines whether program execution breaks when the breakpoint is hit.

To set or modify a breakpoint condition, use the following controls:

Condition check box
Use this check box to turn the condition on or off. The condition has no effect if this box is unchecked.
Condition edit box
Type any valid expression in this box.
Is true
If this button is selected, the debugger evaluates the condition by checking to see if the expression is true. If the expression is true, the condition is satisfied and program execution breaks.
Has changed
If this button is selected, the debugger evaluates the condition by checking to see if the value of the expression has changed since the last time the breakpoint was hit. If the value has changed, the condition is satisfied and program execution breaks.

See Also

Condition | Breakpoints | Debugging UI Reference


Breakpoint Hit Count Dialog Box

The Breakpoint Hit Count dialog box opens when you choose the Hit Count button from the New Breakpoint or Breakpoint Properties dialog box.

The Breakpoint Hit Count dialog box enables you to specify a hit count property for a breakpoint. A breakpoint without a hit count causes program execution to break each time the breakpoint is hit. A breakpoint with a hit count property causes execution to break only on the specified number of hits.

To set or modify a hit count property, use the following controls:

When the breakpoint is hit
This setting determines whether execution should stop when the breakpoint should behave when it is hit. You can choose to:
  • Break always, regardless of hit count. This is the default option. This option has the least effect on program performance, since the debugger does not actually bother to compare the values.
  • Break when the hit count is equal to the counter.
  • Break when the hit count is a multiple of the counter.
  • Break when the hit count is greater than or equal to the counter.

If you choose any option other than the default, an edit box appears next to the list control. Edit the value in this list box to set the hit count value. For example, you might choose break when hit count is equal to and enter 12. This causes execution to stop the 12th time the breakpoint is hit, not on any other hit.

Current hit count
This value shows the number of times the breakpoint has been hit. The debugger keeps track of this value, if you have chosen a setting other than the break always default for When the breakpoint is hit. You can open the Breakpoint Properties dialog box and choose Hit Count to view the current hit count while your program is executing. If you want to break every time the breakpoint is hit, but you also want to keep track of the hit count in the dialog box, choose break when the hit count is a multiple of 1.
Reset hit count
This button resets the value shown for the Current hit count to 1.

See Also

Hit Count | Breakpoints | Debugging UI Reference


Breakpoint Properties Dialog Box

The Breakpoint Porperties dialog box opens when you choose the Breakpoint Properties tool from the Breakpoints window or the Breakpoint Properties command from the shortcut menu. With this dialog box, you can edit the properties that define the breakpoint.

When this dialog box opens, you will see one or more tabs. One tab will be active, depending on the type of breakpoint you are editing. The following table shows the tabs in the Breakpoint Properties dialog box.

To | See
Set properties for a breakpoint on a function at the beginning of the function or at an offset from the beginning | Function, Breakpoint Properties Dialog Box
Set properties for a breakpoint on a source file | File, Breakpoint Properties Dialog Box
Set properties for a breakpoint on a memory location | Address, Breakpoint Properties Dialog Box
Set properties for a breakpoint on a variable | Data, Breakpoint Properties Dialog Box

Below the tabs, you will see the following buttons:

Condition
By default, execution of your program breaks every time the breakpoint is hit. A breakpoint may have a condition that will be tested each time the breakpoint is hit. If the condition is satisfied, your program breaks. Otherwise, execution continues. Choose this button to edit the condition or specify a new condition.
Hit Count
By default, execution of your program breaks every time the breakpoint is hit. A breakpoint can have a specified hit count property. In that case, execution breaks only if the hit count has a specified value. The hit count is the number of times the breakpoint is hit. Choose Hit Count to edit the hit count property or specify a new hit count.

See Also

Breakpoints | Debugging UI Reference


Function, Breakpoint Properties Dialog Box

The following controls allow you to set properties for a breakpoint on a function:

Function
The name of the function on which the breakpoint is set. For a member function, use both the class name and the function name, for example Classy::function.
Line
The source-code line number, measured from the start of the function, at which the breakpoint is set. If this value is 1, the breakpoint is set at the start of the function.
Character
The character within the source-code line where the function is set. If you think of the line number as a row number, the character number would be a column number. In most cases, you can leave this value set to 1, which sets the breakpoint at the start of the line. Sometimes, however, you may have more than one statement on a line. In that case, you can use the Character value to set the breakpoint on a specific statement within the line.
Language
This box should show the programming language that the function is written in. If it i-s not correct, choose the correct language from the drop-down list.


File, Breakpoint Properties Dialog Box

The following controls allow you to set properties for a breakpoint on a source file location:

File
The name, and optional path, of the file in which the breakpoint is set.
Line
The source-code line number, measured from the start of the function, at which the breakpoint is set. If this value is 1, the breakpoint is set at the start of the file.
Character
The character within the source-code line where the function is set. If you think of the line number as a row number, the character number would be a column number. In most cases, you can leave this value set to 1, which sets the breakpoint at the start of the line. Sometimes, however, you may have more than one statement on a line. In that case, you can use the Character value to set the breakpoint on a specific statement within the line.


Address, Breakpoint Properties Dialog Box

The following controls allow you to set properties for a breakpoint on a memory location:

Address
This box contains the memory address where the breakpoint is set, in decimal or hexadecimal. By default, hexadecimal numbers must be preceded by 0x, for example, 0x1002A. The address must be an integer constant. However, you do not have to use the 0x prefix for hexadecimal numbers, if you have chosen the Hexadecimal Display option in the Options dialog box on the Tools menu.
Language
This box should show the programming language for that address. If it is not correct, choose the correct language from the drop-down list.


Data, Breakpoint Properties Dialog Box

The following controls allow you to set properties for a breakpoint on a variable. The program will break execution when the value of the specified variable changes.

Variable
Enter the name of the variable. You can use the context operator to specify a variable outside the current scope.
Items
If the variable is an array or dereferenced pointer, this value specifies the number of elements to watch. Execution breaks if the value of any specified element changes.
Language
This box should show the programming language for the variable. If it is not correct, choose the correct language from the drop-down list.


Breakpoints Window

To open the Breakpoints window, from the Debug menu, choose Windows, and then choose Breakpoints.

To save screen space, the Breakpoints window shares the same frame as the Autos, Locals, This, and Disassembly windows. You can switch back and forth between these windows using the tabs at the bottom of the frame. The title bar changes accordingly.

The Breakpoints window contains a toolbar and a list of breakpoints currently set in your program. The toolbar contains the following tools:

New (Breakpoint)
Opens a dialog box that gives you complete options for creating a new breakpoint.
Delete
Removes whatever breakpoint is currently selected. You cannot undo this operation.
Go to Source Code
Opens a source window, if necessary, and shows you the location where the breakpoint is set.
Go to Disassembly
Shows the Disassembly window and the location where the breakpoint is set.
Columns
Selects the informational columns that appear in the breakpoint list.
Properties
Opens a dialog box that allows you to edit any breakpoint property.

The list contains three columns of information by default:

Name
A descriptive name for the breakpoint, created by the debugger based on the breakpoint's location or other properties. The Name allows you to distinguish between breakpoints and select the one you are interested in.

A check box appears before the name. You can use this check box to enable or disable the breakpoint.

Condition
An optional property that determines whether your program breaks when the breakpoint is reached. The condition can be any valid expression recognized by the debugger. The debugger evaluates the condition and breaks execution only if the condition is satisfied
Hit Count
Another optional property that determines whether your program breaks when the breakpoint is reached. If this property is not set, the debugger stops each time the breakpoint is hit, assuming that the expression shown in Condition column is satisfied. The hit count can notify the debugger to break on the Nth time the breakpoint is reached, or on every multiple of N hits, or on the Nth hit and every time thereafter.

The following columns are not shown by default, but you can add them using the Columns tool:

Language
For a breakpoint set on a variable, which is a data breakpoint), the language in which the debugger evaluates the variable.
Function
The name of the function where the breakpoint is set and the location within the function.
File
The name of the file where the breakpoint is set and the location within the function.
Address
The memory address where the breakpoint is set.
Data
For a breakpoint set on a variable, which is a data breakpoint, the name of the variable.
Program
The name of the program in which the breakpoint is set.

See Also

Breakpoints | Debugging UI Reference


Call Stack Window

To open the Call Stack window, you must be debugging. From the Debug menu, choose Windows and choose Call Stack.

The Call Stack window enables you to view the names of functions on the call stack, parameter types, and parameter values. Call stack information is shown only when the program being debugged is in a break state.

Name column
Shows the name of each function name on the call stack. To allow you to distinguish between various calls to the same function, each name is decorated with the following optional information:
  • module name
  • parameter name
  • parameter type
  • parameter value
  • line number
  • byte offset

    You can turn this information on or off by right-clicking on the Call Stack window and choosing the appropriate options from the shortcut menu.

Language column
Shows the language from which the call to the function is made.

See Also

Using the Call Stack Window | Debugging UI Reference


Debugger Properties On <Machine> Dialog Box

The Debugger Properties On <Machine> dialog box opens when you choose Properties in the Programs dialog box.

Program Types
The types of programs that Visual Studio can debug.
Enable Attach
Set to enable Visual Studio to attach to the selected program type for debugging. Clear to disable attaching to the selected program type.

See Also

Attaching to a Running Program or Multiple Programs | Debugging UI Reference


Disassembly Window

To open the Disassembly window, you must be debugging. From the Debug menu, choose Windows and choose Disassembly.

The Disassembly window shows assembly code corresponding to the instructions created by the compiler. In addition, it can show the following optional information:

  • Memory address where each instruction is located. For native applications, this is the actual memory address. For C# or managed code, it is a pseudomemory address where the beginning of the application's memory space is location zero.
  • Source code from which the assembly code derives.
  • Code bytes, which are byte representations of the actual machine-code instructions.
  • Symbols names for the memory addresses.
  • Line numbers corresponding to the source code.

At the top of the Disassembly window is a toolbar with a single control:

Address
To scroll the screen to a specified memory address, type the address in this box and press return. The toolbar can be hidden or displayed by right-clicking on the Disassembly window and using the shortcut menu. The address can be either a numeric address or a function name.

See Also

Using the Disassembly Window | Debugging UI Reference


Exceptions Dialog Box

The Exceptions dialog box enables you to change the way the debugger handles exceptions or categories of exceptions. From the Debug menu, choose Windows and choose Exceptions.

Exceptions
This box contains a number of tree controls. Each tree represents a category of exceptions, such as C Runtime Errors or NGWS Runtime Exceptions. If you expand a category, you will see the names of individual or subcategories of exceptions. You can choose on any exception or category to select it, then change it is handling using the buttons for When the exception is thrown and If the exception is handled. An icon next to each exception or category name indicates the current setting for When the exception is thrown.
When the exception is thrown
Choose a button from this group to change how the debugger handles the exception immediately after it is thrown and before the program you are debugging has a chance to handle it. The option chosen here effects the exception chosen in Exceptions box. If a category is chosen, the option chosen here effects all the exceptions in that category.
  • Break into debugger

    This option causes the debugger to break execution of your program and so that you can examine the situation and handle the exception yourself. When this option is selected, the icon next to the exception or category name looks like a large red ball with an "X" on it.

  • Continue

    This option allows execution to continue. When this option is selected, the icon next to the exception or category name looks like a large gray ball.

  • Use parent setting

    This option causes a specific exception to use the setting chosen for the parent node, which may be Break into debugger or Continue. When this option is selected, the icon next to the exception or category name looks like a small gray ball.

If the exception is not handled
Choose a button from this group to change how the debugger handles the exception on the second try, which is after the program you are debugging has tried to handle it and failed. The option chosen here affects the exception chosen in Exceptions box. If a category is chosen, the option chosen here affects all exceptions in that category
  • Break into debugger

    This option causes the debugger to break execution of your program and so that you can examine the situation and handle the exception yourself.

  • Continue

    This option allows execution to continue.

  • Use parent setting

    This option causes a specific exception to use the setting chosen for the parent node, which is Break into debugger or Continue.

Find
Choose this button to open a Find Exception dialog box, which you can use to search for an exception name in the Exceptions box. This saves you from having to open each individual tree to find the exception name you are looking for.
Find Next
Choose this button to find another exception with the same name, after you have found the first occurrence with the Find button.
Clear All
Choose this button to delete all user-added exceptions.
Add
Choose this button to add a new exception to a selected category.
Delete
Choose this button to delete a user-added exception.

See Also

Handling Exceptions | Debugging UI Reference


Find Exception Dialog Box

The Find Exception dialog box opens when you choose the Find button from the Exceptions dialog box. Use this dialog box to search for a specific exception within the categories that appear in the Exceptions list box.

Find
Enter the name of the exception you want to search for.

See Also

Handling Exceptions | Debugging UI Reference


Locals Window

To open the Locals window, you must be debugging. From the Debug menu, choose Windows, and then choose Breakpoints.

To save screen space, the Locals window shares the same frame as the Breakpoints, Autos, This, and Disassembly windows. You can switch back and forth between these windows using the tabs at the bottom of the frame. The title bar changes accordingly.

The Locals window contains three columns of information:

Name
This column contains the names of all local variables in the current scope. Structure and array variables have a tree control that you can use to display or hide the elements.
Value
This column shows the value contained by each variable. By default, integer variables are represented in decimal form. You can change the representation to hexadecimal in the Tools dialog box or by right-clicking on the Autos window and choosing the Hexadecimal Display option from the shortcut menu.
Type
This column identifies the data type of each variable listed in the Name column.

See Also

Using the Locals Window | Debugging UI Reference


Memory Window

Note This feature is available for native-code applications only.

To open a Memory window, you must be debugging. From the Debug menu, choose Windows, Memory, and then choose Memory 1, Memory 2, Memory 3, or Memory 4. You can open these Memory windows in any order.

You can use a Memory window to view large buffers, strings, and other data that do not display well in the Watch or Variables windows.

A toolbar at the top of the Disassembly window has a single control:

Address
To scroll the screen to a specified memory address, type the address in this box and press return. The address can be either a numeric address, a function name, or an expression.

The toolbar can be hidden or displayed using the shortcut menu.

See Also

Using the Memory Window | Debugging UI Reference


Modules Window

To open the Modules window, you must be debugging. From the Debug menu, choose Windows and choose Modules.

The Modules window lists the modules, which are DLL or EXE files, used by your program. It shows the following information for each module:

Name
Module name, which has a .dll or .exe file name extension.
Address
Memory locations occupied by the module.
Path
Path name of the DLL or EXE on your hard disk.
Order
Load order. The first module loaded is number 0.
Version
Version number of the module.
Information
Whether debug information for the module has been loaded.

By default, the Modules window sorts modules by load order. However, you can sort by any column by chooseing the button at the top of the column.

See Also

Debugging UI Reference


New Breakpoint Dialog Box

The New Brakpoint dialog box opens when you choose the New Breakpoint command from the Debug menu or the New Breakpoint tool from the Breakpoints window. With this dialog box, you can create a new breakpoint of any type, such as function, file, address, or data.

This dialog box contains four tabs, each of which contains controls for setting a specific type of breakpoint. The following table shows the tabs in the New Breakpoint dialog box.

To | See
Set a breakpoint on a function at the beginning of the function or at an offset from the beginning | Function, New Breakpoint Dialog Box
Set a breakpoint at a specific location within a specified file | File, New Breakpoint Dialog Box
Set a breakpoint at a specific memory location | Address, New Breakpoint Dialog Box
Set a breakpoint on a variable | Data, New Breakpoint Dialog Box

Below the tabs, you will see the following buttons:

Condition
By default, execution of your program breaks every time the breakpoint is hit. If you choose this button, you can specify a condition that will be tested each time the breakpoint is hit. If the condition is satisfied, your program breaks. Otherwise, execution continues.
Hit Count
By default, execution of your program breaks every time the breakpoint is hit. Choose this button if you want execution to break on a specified hit count instead.

See Also

Using the Breakpoints Window | Breakpoints | Debugging UI Reference


Function, New Breakpoint Dialog Box

The following controls allow you to set properties for a breakpoint on a function:

Function
The name of the function on which the breakpoint is set. For a member function, use both the class name and the function name, for example Classy::function.
Line
The source-code line number, measured from the start of the function, at which the breakpoint is set. If this value is 1, the breakpoint is set at the start of the function.
Character
The character within the source-code line where the function is set. If you think of the line number as a row number, the character number would be a column number. In most cases, you can leave this value set to 1, which sets the breakpoint at the start of the line. Sometimes, however, you may have more than one statement on a line. In that case, you can use the Character value to set the breakpoint on a specific statement within the line.
Language
This box should show the programming language that the function is written in. If it is not correct, choose the correct language from the drop-down list.


File, New Breakpoint Dialog Box

The following controls allow you to set properties for a breakpoint on a source file location:

File
The name and optional path of the file in which the breakpoint is set.
Line
The source-code line number, measured from the start of the function, at which the breakpoint is set. If this value is 1, the breakpoint is set at the start of the file.
Character
The character within the source-code line where the function is set. If you think of the line number as a row number, the character number would be a column number. In most cases, you can leave this value set to 1, which sets the breakpoint at the start of the line. Sometimes, however, you may have more than one statement on a line. In that case, you can use the Character value to set the breakpoint on a specific statement within the line.


Address, New Breakpoint Dialog Box

The following controls allow you to set properties for a breakpoint on a memory location:

Address
This box contains the memory address where the breakpoint is set, in decimal or hexadecimal. By default, hexadecimal numbers must be preceded by 0x, for example, 0x1002A. The address must be an integer constant. You do not need to use the 0x prefix for hexadecimal numbers, however, if you have chosen the Hexadecimal Display option in the Options dialog box found on the Tools menu.
Language
This box should show the programming language for that address. If it is not correct, choose the correct language from the drop-down list.


Data, New Breakpoint Dialog Box

The following controls allow you to set properties for a breakpoint on a variable. The program will break execution when the value of the specified variable changes.

Variable
Enter the name of the variable. You can use the context operator to specify a variable outside the current scope.
Items
If the variable is an array or dereferenced pointer, this value specifies the number of elements to watch. Execution breaks if the value of any specified element changes.
Language
This box should show the programming language for the variable. If it is not correct, choose the correct language from the drop-down list.


Programs Dialog Box

The Programs dialog box opens when you select Programs from the Debug menu.

The Programs dialog box enables you to view and manipulate programs in a Visual Studio solution. Using this dialog box, you can debug multiple programs at the same time in a single workspace.

Transport
Selects between a local port and TCP/IP for attaching to a program on another machine.
Machine
Selects the local machine or a remote machine for attaching to a program for debugging. Choose ... to browse for a machine on the selected transport.
Properties
Allows you to enable or disable attaching to a program type, such as Win32, NGWS runtime, or script, using the Debugger Properties On <Machine> dialog box.
Available Properties
This group displays information on all programs available for debugging.
Process
The program or process name, which is usually an .exe file.
Id
The process identification number assigned by the operating system.
Title
The title in the program's title bar, if any. This title also appears in the taskbar.
Type
The type of program, such as Win32 or NGWS runtime.
Debugger
If the program is currently being debugged, this identifies the debugger and the machine the debugger is running on, for example, Visual Studio debugger on BensMachine.
Attach
Choose to debug the program selected in Available Processes. This brings up the Attach to Process dialog box.
Refresh
Because programs can start and stop in real time while the Programs dialog box is open, the Available Processes list may not be up to date. Choose this button to refresh the list.
Debugged Processes
This group displays information on all processes currently attached for debugging.
Machine
For a debugged process, this identifies the machine the process is running on.
Port
For a debugged process, this identifies the port through which the machine is attached.
Break
Choose to break execution of the program selected in Debugged Processes.
Detach
Choose to stop debugging, or detach from, the program selected in Debugged Processes.
Terminate
Choose to terminate the program selected in Debugged Processes.
When debugging is stopped
For the program selected in Debugged Processes, this setting determines whether the program terminates or merely detaches from the debugger and continues to run when you stop debugging.

See Also

Attaching to a Running Program or Multiple Programs | Debugging UI Reference


QuickWatch Dialog Box

The QuickWatch dialog box opens when you choose QuickWatch from the Debug menu. The debugger must be in a break state.

The QuickWatch dialog box enables you to view variables and to register contents for native-code applications, C/C++ expressions, assembly-language expressions, Visual Basic expressions, SQL expressions, and Script expressions.

In addition, you can use the QuickWatch dialog box to change the value of any variable except const variables or the contents of any register.

The Current Value box displays the value and type for variables, registers, and expressions you have specified. You can add a variable, register, or expression to this box by typing it in the Expression box.

Expression
In this box, you can type a variable name or any valid expression recognized by the debugger. The drop-down list contains previously entered expressions that you can select to save the trouble of retyping.
Recalculate
Choose this button to evaluate the variable or expression in the Expression box and display the results in Current value.
Add Watch
Choose this button to add the contents of Expression box to the Watch window.
Current value
When you choose Recalculate, this box displays the expression from the Expression box in the Name column, the value of the expression in the Value column, and the data type of the value in the Type column.

See Also

Debugging UI Reference


Registers Window

Note This feature is available for native-code applications only.

To open the Registers window, you must be debugging. From the Debug menu, choose Windows and choose Registers.

The Registers window displays register contents. If you keep the Registers window open as you step through your program, you can see register values change as your code executes. Values that have changed recently appear in red.

See Also

Using the Registers Window | Debugging UI Reference


Running Documents Window

To open the Running Documents window, you must be debugging. From the Debug menu, choose Windows and choose Running Documents.

The Running Documents window is useful for script debugging. It displays a list of documents that are currently loaded into the process you are running.

Documents List
A hierarchical list of documents are their paths.

See Also

Using the Running Documents Window | Debugging UI Reference


This Window

To open the This window, you must be debugging. From the Debug menu, choose Windows and choose This.

To save screen space, the This window shares the same frame as the Breakpoints, Autos, Locals, and Disassembly windows. You can switch back and forth between these windows using the tabs at the bottom of the frame. The title bar changes accordingly.

The This window contains three columns of information:

Name
This column shows the object pointed to by the This pointer in C/C++ and the me object in Visual Basic. A tree control allows you to expand the object to see elements. When the object is expanded, the name of each element appears in this column.
Value
This column shows the value contained by each variable. By default, integer variables are represented in decimal form. You can change the representation to hexadecimal in the Tools dialog box or by right-clicking on the Autos window and choosing the Hexadecimal Display option from the shortcut menu.
Type
This column identifies the data type of each variable listed in the Name column.

See Also

Using the This Window | Debugging UI Reference


Threads Window

To open the Threads window, from the Debug menu, choose Windows, and then choose Threads.

When you debug a multithreaded program, you can use the Threads window to view thread information and manipulate threads.
Leftmost column
An arrow in this column marks the active thread.
Id
A DWORD that uniquely identifies each thread.
Name
The name of the thread.
Location
The function name or address associated with the thread.
Priority
Numerical priority of the thread.
Suspend
Suspend count of the thread, which can vary from 0 through 127. This number is changed by calls to SuspendThread and ResumeThread. Each call increments or decrements the suspension count by one.

See Also

Using the Threads Window | Debugging UI Reference


Watch Window

To open the Watch window, the debugger must be running or in a break state. From the Debug menu, choose Windows and choose Watch.

Name
In this column you can type any valid expression recognized by the debugger.
Value
The debugger evaluates the expression and places the result in this column. If the expression is a variable or register name, you can edit the value in this column to change the contents of the variable or register. You cannot edit const variables, and you cannot view or edit registers in non-native-code applications.
Type
This column displays the data type of the variable or expression.

See Also

Using the Watch Window | Debugging UI Reference


General, Debugging, Options Dialog Box

The General pane of the Options dialog box allows you to set general debugging options.

Hexadecimal display
Select this option to display integers in hexadecimal format rather than binary.
Allow hexadecimal input without prefix
Select this option if you want the debugger information windows to accept input as hexadecimal as default (without the 0x prefix).
Warn if no symbols on launch
Select this option to display a dialog box warning you when you try to debug a program for which the debugger has no symbolic information.
Confirm correct file was found when finding source
Select this option to display a dialog box asking you to confirm that the debugger found the correct source file.
In break mode, only stop execution of the current program
Allows other attached programs to continue running when you break the current program.
Color text of current statement and breakpoints
Uses color to call out the current statement and statements where breakpoints are set.
Use CodeSense to verify breakpoints
Uses CodeSense to verify that breakpoints are valid.
Insert breakpoints in Active Server Pages for breakpoints in client script
When a breakpoint is set in a client script, inserts a corresponding breakpoint in the associated Active Server Page.
Just-In-Time Debugging/Attach On This Machine
Select to choose the types of applications (Win32 or NGWS runtime, for example) that can be attached for debugging (including just-in-time debugging).

See Also

Debugging UI Reference


Edit and Continue, Debugging, Options Dialog Box

The Edit and Continue pane of the Options dialog box allows you to set options for Edit and Continue.

Enable Edit and Continue
Select this box to enable Edit and Continue.
Invoked by Debug Commands
When this box is selected, execution commands such as Step can invoke Edit and Continue.
Ask me first
When this box is selected, execution commands open a dialog box before invoking Edit and Continue. This dialog box gives you a chance to cancel Edit and Continue.
Warn me about stale code
In some cases, Edit and Continue cannot apply code changes to the executable immediately, but may be able to apply the code changes later if you continue debugging. This occurs if you edit a function that calls the current function or if you add more than 64 bytes of new variables to a function on the call stack. When this happens, the original code continues to execute until the function exits and is called again. Edit and Continue updates the call at that time. Until the call exits, the source window shows the original code in gray. Because this code is has been superceded by code changes, it is outdated or stale. You cannot edit stale code. The debugger warns you about stale code, by default. You can turn the warning off, if you prefer.
Relink after debugging
Edit and Continue does not invoke custom build steps. If your program uses custom build steps, you may want to rebuild manually so that custom build steps can be invoked. In that case, you can disable relinking after Edit and Continue to ensure that you are prompted to manually rebuild.
Allow Precompiling
By default, Edit and Continue loads and processes precompiled headers in the background to speed up processing of code changes. Loading precompiled headers requires allocation of physical memory, which can be a problem if you are compiling on a machine with limited RAM. Under Windows NT or Windows 2000, you can determine if this might be a problem by using the Windows NT Task Manager to determine the amount of available physical memory while you are debugging. If this amount is greater than the size of your precompiled headers, Edit and Continue should have no problem. If the amount is less than the size of your precompiled headers, you can prevent Edit and Continue from loading precompiled headers in the background

See Also

Debugging UI Reference


Find Source, Debugging, Options Dialog Box

The Find Symbol pane of the Options dialog box specifies where the debugger will look for source files when debugging the solution.

Look for source files in the following directories
This box contains a list of directories in which the debugger searches for source files when debugging the solution.
Do not look for these source files
In this box, you can enter the names of any source files that you do not want the debugger to read. If the debugger finds one of these files in one of the directories specified above, it will ignore it.

See Also

Debugging UI Reference


Find Symbol, Debugging, Options Dialog Box

The Find Symbol pane of the Options dialog box specifies where the debugger will look for symbols when debugging the solution.

Look for symbol files in the following directories
This box contains a list of directories in which the debugger searches for symbol files when debugging the solution.
Do not look for these symbol files
In this box, you can enter the names of any files that you do not want the debugger to read symbols from. If the debugger finds one of these files in one of the directories specified above, it will ignore it.

See Also

Debugging UI Reference


Native, Debugging, Options Dialog Box

The Native pane of the Options dialog box allows you to set the following options for debugging native Win32 applications.

RPC Debugging
Select this control if you want to step into COM remote procedure calls when debugging.
Load COFF and Exports
Select this box to load COFF-format debugging information or DLL export tables. COFF is a format used by some other debuggers. You can find COFF-format information in the MSVBVM50.DBG file shipped provided with Visual Basic 5.01, for example. Symbolic information from DLL export tables can be useful if you are working with Windows 95/98 system DLLs, Windows messages, Windows procedures (WindowProcs), COM objects, or marshalling. Reading COFF and DLL export information entails some overhead, so this capability is turned off by default.

To see whether a DBG file contains CodeView- or COFF-format information, use dumpbin /headers. Look in the Debug Directories section of the output file for COFF (coff) or CodeView (cv) entries.

To see what symbols are available in the export table of a DLL, use dumpbin /exports. Symbols are available for any 32-bit system DLL. By reading the dumpbin /exports output, you can see the exact function name, including non-alphanumeric characters. This is useful for setting a breakpoint on a function. Function names from DLL export tables may appear truncated elsewhere in the debugger. The calls are listed in the calling order, with the current function (the most deeply nested) at the top

See Also

Debugging UI Reference


Topic Not Found

No matching topic was found. The link may be out of date, incorrectly authored, or the topic may not be available in this release.

You may be able to find the topic by using the index or search tab instead.


Copyright

NGWS SDK Documentation

This is a preliminary document and may be changed substantially prior to final commercial release. This document is provided for informational purposes only and Microsoft makes no warranties, either express or implied, in this document. Information in this document, including URL and other Internet Web site references, is subject to change without notice. The entire risk of the use or the results of the use of this document remains with the user. Unless otherwise noted, the example companies, organizations, products, people and events depicted herein are fictitious and no association with any real company, organization, product, person or event is intended or should be inferred. Complying with all applicable copyright laws is the responsibility of the user. Without limiting the rights under copyright, no part of this document may be reproduced, stored in or introduced into a retrieval system, or transmitted in any form or by any means (electronic, mechanical, photocopying, recording, or otherwise), or for any purpose, without the express written permission of Microsoft Corporation.

Microsoft may have patents, patent applications, trademarks, copyrights, or other intellectual property rights covering subject matter in this document. Except as expressly provided in any written license agreement from Microsoft, the furnishing of this document does not give you any license to these patents, trademarks, copyrights, or other intellectual property.

Unpublished work. © 1999 - 2000 Microsoft Corporation. All rights reserved.

Microsoft, MS-DOS, Windows, Windows NT, Active Directory, ActiveX, Authenticode, FrontPage, IntelliSense, JScript , Outlook, Visual Basic, Visual Basic Scripting Edition (VBScript), Visual C++, Visual Studio, and Win32 are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries.

The names of actual companies and products mentioned herein may be the trademarks of their respective owners.