Chapter 3
IN THIS CHAPTER
Setting, enabling, and disabling breakpoints
Temporarily setting or disabling a breakpoint
Inspecting a variable
Watching any or all local and global variables
Sometimes, code breaks. The word break has different meanings among the people using it in the coding world. When programmers talk about breaking the code, it may mean that the programmer made a mistake and the code no longer works. It could also mean that a change in a library causes the code to malfunction despite a lack of errors caused by the programmer. But this chapter uses a different definition for break. When you’re debugging an application, you can have the application run until it gets to a certain line in the code. The debugger then stops at that line, and you can look at the values of variables, inspect the code, or even change the variables. When the application stops, that’s called breaking. It stops on that particular line because you put a breakpoint on that line.
This chapter discusses setting and manipulating breakpoints in your code (if nothing else in your code is broken). You also inspect and modify various aspects of your code, such as variables, after your code stops at a breakpoint. You also see how to use watches to keep track of certain variables or expressions.
A breakpoint is a place in your code where you tell the debugger to stop. The sections that follow discuss breakpoints. You use the Breakpoints
sample code, shown in Listing 3-1, for these sections. Make sure that you compile it with debug information on.
LISTING 3-1: Using an Application for Breakpoints and Inspections
#include <iostream>
using namespace std;
class BrokenMirror {
private:
int NumberOfPieces;
public:
int GetNumberOfPieces();
void SetNumberOfPieces(int newamount);
BrokenMirror() : NumberOfPieces(100) {}
};
int BrokenMirror::GetNumberOfPieces() {
return NumberOfPieces;
}
void BrokenMirror::SetNumberOfPieces(int newamount) {
newamount = newamount * 20;
NumberOfPieces = newamount;
}
int main() {
BrokenMirror mirror;
mirror.SetNumberOfPieces(10);
cout << mirror.GetNumberOfPieces() << endl;
return 0;
}
Compile the application in Listing 3-1 (with debug information turned on). Look at the left margin of the window, to the right of the line numbers. Figure 3-1 shows a small octagon on line 14. When you view the IDE, this octagon is red. The red octagon is a breakpoint. To set this breakpoint in your own code, click in the area between the left margin and the code (or right-click the line of code and choose Toggle Breakpoint from the context menu), as shown in the figure on line 14. If you haven’t done so, click the mouse in the left margin of the int BrokenMirror::GetNumberOfPieces()
line. You see a red octagon appear in the left margin. You just placed a breakpoint on that line.
Click again in the left margin of the same line. The red octagon disappears. When the octagon disappears, the breakpoint is gone.
Finally, click a third time, because for now you do want a breakpoint there.
Run the application by clicking the Debug/Continue button (the icon with the red, right-pointing arrow on it) on the Debugger toolbar. If you don’t see the Debugger toolbar, choose View ⇒ Toolbars ⇒ Debugger to place a check mark next to the Debugger entry. (Don’t click the Run button, which is the green right-pointing triangle on the Compiler toolbar, because choosing this option simply runs the application without debugging it.) When you click Debug/Continue, the console window may pop in front, so just click the Code::Blocks window to bring it back to the front.
FIGURE 3-1: Code::Blocks displays any breakpoints you set using a red octagon.
The application runs until it gets to the breakpoint you chose for the int BrokenMirror::GetNumberOfPieces()
line, as shown in Figure 3-2. Note that execution actually ends with the opening curly brace because this is the beginning of execution for this function. The yellow, right-pointing triangle tells you the current instruction that the Code::Blocks debugger will execute. You can now click the Next Line button (the button with two squares and an arrow pointing from the upper square to the lower square) to move to the next line, or you can click Debug/Continue to run the rest of the application.
You may have times when you have several breakpoints set and you want to turn them off momentarily but don’t want to lose them because you may want to turn them back on later. You can do this by disabling the breakpoints. Disabling the breakpoint is faster than removing the breakpoints and then going back and finding them again to turn them back on. Use the following steps to disable a breakpoint:
Right-click the red octagon on the left side of the editor and choose Edit Breakpoint from the context menu.
You see the Edit Breakpoint dialog box, as shown in Figure 3-3.
FIGURE 3-2: Debug mode tells Code::Blocks to stop execution when it reaches the breakpoint.
FIGURE 3-3: Use the Edit Breakpoint dialog box to enable and disable breakpoints.
Clear the Enabled option and click OK.
Code::Blocks disables the breakpoint so that it no longer stops application execution.
Many debuggers show a disabled breakpoint using a hollow red circle (or sometimes an octagon). Code::Blocks turns the red octagon gray instead. However, you’ll still want to see that disabling the breakpoint actually does work. Set a new breakpoint after the line that reads return NumberOfPieces;
(on the curly brace). Click Debug/Continue and you’ll see that the debugger bypasses the first breakpoint and stops at the second, as shown in Figure 3-4.
FIGURE 3-4: Disabled breakpoints don’t stop application execution.
In some cases, you want to enable or disable a number of breakpoints. Use the following steps to perform this task:
Choose Debug ⇒ Debugging Windows ⇒ Breakpoints.
You see the Breakpoints window, shown in Figure 3-5. The window shows the kind of breakpoint (with a red or gray octagon to tell you whether it’s enabled or disabled), the breakpoint location, the line in the code file where the breakpoint appears, and the name of the debugger being used.
FIGURE 3-5: Use the Breakpoints window to access a number of breakpoints at one time.
Right-click the breakpoint entry and choose one of the management options from the context menu.
The management options help you control one or more breakpoints. You can perform the following tasks using the management options:
When you stop at a breakpoint in an application, you can do more than just look at the code. You can have fun with it! You can look at the current values of the variables, and you can change them.
The Breakpoints2
example, shown in Listing 3-2, is a sample application that you can use to try these examples of inspecting, changing, and watching variables. Please note that this application is similar to Listing 3-1, earlier in this chapter, but you should see some differences. Specifically, it adds a line to the SetNumberOfPieces()
method:
newamount = newamount * 20;
The example adds a new function called SpecialMath()
and an i
variable to main()
that is initialized to 10
. The code then manipulates i
and passes it into the SetNumberOfPieces()
function.
LISTING 3-2: Using an Application for Breakpoints and Inspections
#include <iostream>
using namespace std;
class BrokenMirror {
private:
int NumberOfPieces;
public:
int GetNumberOfPieces();
void SetNumberOfPieces(int newamount);
BrokenMirror() : NumberOfPieces(100) {}
};
int BrokenMirror::GetNumberOfPieces() {
return NumberOfPieces;
}
void BrokenMirror::SetNumberOfPieces(int newamount) {
newamount = newamount * 20;
NumberOfPieces = newamount;
}
int SpecialMath(int x)
{
return x * 10 - 5;
}
int main() {
int i = 10;
BrokenMirror mirror;
i = i + SpecialMath(i);
mirror.SetNumberOfPieces(i);
cout << mirror.GetNumberOfPieces() << endl;
// Clear this comment if you want the application to
// stop to display the results.
// system("PAUSE");
return 0;
}
When you run this application by clicking Run, you should see an output value of 2100
.
To watch the variables in your application, follow these steps:
int i = 10;
line in main()
.When the debugger stops at the breakpoint, choose Debug ⇒ Debugging Windows ⇒ Watches.
You see the Watches window, as shown in Figure 3-6. Notice that the Watches window automatically includes i
and mirror
. If you click the + next to mirror, you can drill down to see NumberOfPieces
.
Notice that the values in i
and NumberOfPieces
are random because the code hasn’t assigned values to them yet. The values you see will differ from those shown in Figure 3-6. This is the reason you never want to use a variable until after you assign a value to it. In this case, the variables are shown in red because C++ has just created them.
Objects such as
mirror
contain not only variables but also other objects. When an object contains a child object, the child object will also have a plus sign next to it. To see the contents of this child object, simply click the plus sign next to it. You can keep drilling down until you reach the end of the object list.
FIGURE 3-6: The Watches window shows the value of variables and objects.
int i = 10;
The application changes the value of i
to 10
, as shown in Figure 3-7. The variable is still shown in red because its value has just changed. However, notice that NumberOfPieces
is now shown in black because its value hasn’t changed since the last instruction.
FIGURE 3-7: Assigning a value to i
changes its value in the Watches window.
Click Next Line on the Debugger toolbar.
The entry for i
turns black to show that it has remained stable during the execution of this command. However, NumberOfPieces
is now shown in red and has a value of 100. The use of red for changed variables and black for unchanged variables makes it easy to determine which variables have changed.
Click Debug/Continue.
The application ends.
Sometimes you need to verify that the application works as intended by simulating changes that might occur in the code. In many cases, this means changing a value from its default to the value you want to test. Fortunately, the Watches window provides the means to perform this task. Follow these steps to see how you can change variable values:
i = i + SpecialMath(i);
line in main()
.When the debugger stops at the breakpoint, choose Debug ⇒ Debugging Windows ⇒ Watches.
You see the Watches window (refer to Figures 3-6 and 3-7). The values of i
and NumberOfPieces
appear as before. However, you can’t change these values; you can only view them.
Type i in the first column of the last row of the Watches window and press Enter.
You see the current value of i
, which is 10
. Notice also that you see a variable type, int
, in the third column, as shown in Figure 3-8. This entry is also in red because you’ve just added it to the Watches window.
FIGURE 3-8: Adding a watch to the window presents additional information.
Select the value, 10
, in the second column of the Watches window for the i
you added, type 100, and click the next line of the Watches window.
Code::Blocks changes the value of i
to 100
. The i
variable entry, which used to be black, has turned red because you changed the value. Notice that the copy of i
in the Locals area has also changed in both value and color.
return 0;
Notice that the output of the application (as well as the value of NumberOfPieces
in the Watches window) has changed to 21900. Normally the output is 2100. The difference occurs because the value of i
was changed.
Click Debug/Continue.
The application ends.