Chapter 3

Stopping and Inspecting Your Code

IN THIS CHAPTER

check Setting, enabling, and disabling breakpoints

check Temporarily setting or disabling a breakpoint

check Inspecting a variable

check 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.

Tip The examples in this chapter rely on the debugger supplied with the Code::Blocks IDE. If you use a different product, the debugger will probably work about the same but not precisely the same. For example, you can do everything shown here using Microsoft Visual C++. The keystrokes and mouse clicks may be different, but the features are present. Make sure to check the vendor documentation for precise details on using your debugger.

Remember To work through the examples in this chapter, you must compile with debug information turned on. (In Code::Blocks, you can compile with debug information by choosing Debug in the Build Target field of the Compiler toolbar. If you can’t see the Compiler toolbar, choose View ⇒ Toolbars ⇒ Compiler to place a check mark next to the Compiler entry.) When you develop software, you should always have debug information on. That way, you’re always ready to debug your code and fix things. Only when you’re ready to release the product formally should you recompile it without debug information. (You should still perform a full test of the software again without debug information, just to make sure that it functions correctly.)

Remember You don’t have to type the source code for this chapter manually. In fact, using the downloadable source is a lot easier. You can find the source for this chapter in the \CPP_AIO4\BookIV\Chapter03 folder of the downloadable source. See the Introduction for details on how to find these source files.

Setting and Disabling Breakpoints

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;
}

Setting a breakpoint in Code::Blocks

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.

Snapshot of Code::Blocks displaying any breakpoints you set using a red octagon.

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.

Enabling and disabling breakpoints

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:

  1. 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.

    Snapshot of debugging mode tells Code::Blocks to stop execution when it reaches the breakpoint.

    FIGURE 3-2: Debug mode tells Code::Blocks to stop execution when it reaches the breakpoint.

    Snapshot of using the Edit Breakpoint dialog box to enable and disable breakpoints.

    FIGURE 3-3: Use the Edit Breakpoint dialog box to enable and disable breakpoints.

  2. 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.

Snapshot of the disabled breakpoints that don't stop application execution.

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:

  1. 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.

    Snapshot of using the Breakpoints window to access a number of breakpoints at one time.

    FIGURE 3-5: Use the Breakpoints window to access a number of breakpoints at one time.

  2. 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:

    • Open the breakpoint in the editor so that you can see where it’s located.
    • Edit the breakpoint, which displays the Edit Breakpoint dialog box, shown in Figure 3-3.
    • Remove the selected breakpoint.
    • Disable the selected breakpoint.
    • Add a bookmark so that you can find this location in the code with greater ease. When you choose this option, you see a right-pointing blue arrow between the line number and the code. Use the Edit ⇒ Bookmarks menu options to work with bookmarks.
    • Remove all the breakpoints you have set in the application.

Watching, Inspecting, and Changing Variables

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.

Watching the variables

To watch the variables in your application, follow these steps:

  1. Compile this application using a debug build (Build ⇒ Select Target ⇒ Debug) rather than a release build.
  2. Set a breakpoint at the int i = 10; line in main().
  3. Click Debug/Continue.
  4. 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.

    Remember 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.

    Snapshot of the Watches window showing the value of variables and objects.

    FIGURE 3-6: The Watches window shows the value of variables and objects.

  5. Click the Next Line button on the Debugger toolbar so that you are one line beyond the following line:

    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.

    Snapshot of assigning a value to i changes its value in the Watches window.

    FIGURE 3-7: Assigning a value to i changes its value in the Watches window.

  6. 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.

  7. Click Debug/Continue.

    The application ends.

  8. Remove any breakpoints you’ve set in the example application.

Changing values

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:

  1. Set a breakpoint at the i = i + SpecialMath(i); line in main().
  2. Click Debug/Continue.
  3. 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.

  4. 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.

    Snapshot of adding a watch to the window presents additional information.

    FIGURE 3-8: Adding a watch to the window presents additional information.

  5. 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.

  6. Click Next Line three times so that the instruction pointer is on the line that reads

    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.

  7. Click Debug/Continue.

    The application ends.