This chapter discusses how to use breakpoints so you can stop your program to examine its code or data. It includes sections on the following:
The Watcom Debugger uses the single term breakpoint to refer to the group of functions that other debuggers often call breakpoints, watchpoints, and tracepoints.
A breakpoint is traditionally defined as a place in your program where you want execution to stop so that you can examine program variables and data structures. A watchpoint causes your program to be executed one instruction or source line at a time, watching for the value of an expression to become true. Don't confuse a watchpoint with the watch window. A tracepoint causes your program to be executed one instruction or source line at a time, watching for the value of certain program variables or memory-referencing expressions to change.
In the Watcom Debugger:
The Watcom Debugger unifies these three concepts by defining three parts to a breakpoint:
You can specify a countdown, which means that a condition must be true a designated number of times before the breakpoint is triggered.
When a breakpoint is triggered, several things can happen:
In this chapter, you'll learn about the breakpoint, including how to set simple breakpoints, conditional breakpoints, and breakpoints that watch for the exact moment when a program variable, expression, or data object changes value.
When debugging, you often want to set a few simple breakpoints to make your program pause execution when it executes certain code. You can set or clear a breakpoint at any location in your program by placing the cursor on the source code line and selecting Toggle from the Break menu or by clicking on the button to the left of the source line. You can set breakpoints in the assembly window in a similar fashion. Setting a break-on-write breakpoint is equally simple. Select the variable with the right mouse button and choose Break.
Breakpoints have three states, as indicated by the button to the left of the source line:
State | Button |
---|---|
enabled | [!] |
disabled | [.] |
cleared (non-existent) | [ ] |
The same buttons also appear in the Assembly window and the Break window to indicate the state of a breakpoint.
Some lines in your program don't contain any machine code to execute, so you can't set a breakpoint on them. The compiler doesn't generate machine code for comments and some C constructs. All lines of code in your program that can have a breakpoint on them have a button to the left of the source line. You can click on them to change their current state. |
Choosing Toggle from the Break menu (F9) toggles between the three different breakpoint states:
You can use the Break menu to control your breakpoints. Operations including creating new breakpoints, changing a breakpoint's state, and viewing a list of all breakpoints:
Disabled and cleared breakpoints aren't the same. If you disable a breakpoint, you can re-enable it and retain the information about the breakpoint (for example, conditions, countdown, and actions). When you clear a breakpoint, you lose all information about the breakpoint. If you disable a breakpoint, and press F9 twice to enable, you lose the information about the breakpoint because you cleared it before you re-enabled it. To enable a disabled breakpoint without losing the breakpoint information, use the Breakpoint Option dialog or the Breakpoint window. |
The Break window displays each breakpoint and its state. It appears when you select the View All from the Break menu. A breakpoint button appears at the left of each line. You can click on this button to enable and disable a breakpoint. Unlike the source and assembly windows, the button doesn't clear the breakpoint. Next appears the address of the breakpoint. Finally, for break-on-execute breakpoints, the source or assembly code at the breakpoint location is displayed. For break-on-write breakpoints, the current value of the location is displayed in hex.
To modify any breakpoint, double-click on it, or by cursor to it and press Enter. The Breakpoint Options dialog appears. Press the right mouse button to access the following popup menu items:
The Breakpoint dialog appears when you:
It allows you to define the breakpoint and set all of its conditions. A description of the items in the dialog follows.
When you choose At Cursor, this field already contains an address that describes the line of code that the cursor is on. The format of the address tag is symbol+offset, where symbol is the name of the nearest function, and offset is the distance in bytes past that symbol where the breakpoint is defined. It's normally best not to edit this field. To change the line of source code, leave the dialog, move the cursor to where you want the breakpoint, and use the At Cursor command again.
When you choose New, this field is empty. You can type any valid address expression in this field. It can be the name of a function or a global variable. Refer to the Expression Handling chapter for more information about address expressions. In the dialog, you can click the Symbols... button as a shortcut. You can type a partial symbol, such as foo, and the Symbol button shows you a list of symbols that start with foo. You can then choose one of these symbols by clicking on it, or by pressing Enter. Note that the first time you use the Symbols... button in a debugging session, it may take a while, as the debugger sorts the symbol table for the program.
Be careful when using local (stack) variables for a break-on-write breakpoint. As soon as execution leaves the scope of the variable, the memory changes at random since the variable doesn't really exist any more and the memory is used for other variables. Also, if execution enters that variable's scope again, the variable may not have the same memory address. |
If you want to use this field to execute a statement in the language you're debugging, you need to use a DO command in front of the statement. For example, you could enter DO i = 10 to have the value of 10 assigned to i each time the breakpoint is triggered.