<

Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x

Breakpoint Tips for C/C++ Visual Studio 2008 Debugger - Part 2

Published on
26,771 Points
6,071 Views
7 Endorsements
Last Modified:
Awarded

Introduction

This article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article located in Part 1, and as you get more familiar with the debugger, you may be interested in some additional miscellaneous tips in Part 3.



As assignments become more complicated (e.g., more loop iterations, more recursion, more function nesting), the tips shown below may further help improve your productivity.

For this article, all projects are built using a “General Empty” project. The first project reads in a very large list of scrabble words, and determines the largest set of anagrams in the list.

TABLE   OF   CONTENTS

1.  Conditional Breakpoints
2.  Hit Count Breakpoints
3.  Touch and Go Breakpoints (a.k.a. Tracepoints)
4.  Exception Breakpoints
4.1.  Change How the Debugger Handles an Exception
4.2.   Adding a User Defined Exception
4.3.   Breaking on a User Defined Exception
5.  Run To Cursor (Create a Temporary Breakpoint)
6.  List of Breakpoints

1.  Conditional Breakpoints

The program is reading in thousands of words. Suppose you suspect there is a problem after the program reads in a word beginning with “lap”. Rather than hit F5 thousands of times to get there, you can set up a conditional breakpoint which will stop when the first three letters are “lap”. After setting a breakpoint, right-click on it, and select Condition; then enter the desired condition:
cstr[0]=='l' && cstr[1]=='a' && cstr[2]=='p'

Open in new window

Figure 1 shows how to force a break only when the first three characters of a c-style string begin with "lap".  Also, notice that the breakpoint symbol now has a white +sign in it within the red circle, designating a conditional breakpoint.Condition-Breakpoint
Figure 1  Condition Breakpoint

Note that when the debugger reaches the above conditional breakpoint, it will temporarily stop the control flow of the program to evaluate the condition. If the condition is false, the debugger agent transfers control back to the program. After resuming the program, you can see in Figure 2 that the found word is, not surprisingly, “lap’. Breakpoint Condition True
Figure 2 Breakpoint Condition True

Now that you have found the word “lap”, if you hit F5 again, you will stop on the next word, which is “lapdog”. If you then toggle the Breakpoint Condition from “Is true” to “Has changed”, then the program will stop when the Boolean condition changes; in this case the program stops on a transition is from True to False. This occurs when the word does not begin with “lap”. So, the word on which the program stops is “larcenies”.

You may notice that your debugging session takes a bit longer when you have conditional breakpoints. However, if used wisely, this approach will prove very significant in the overall debugging of your program.

2.  Hit Count Breakpoints

Another condition that you can use to qualify the breakpoint stopping rule is the Hit Count.
After setting a breakpoint, you can right-click on it, and select Hit Count. This option allows four different reasons for stopping at the breakpoint. They are shown in Figure 3. The first option, "break always", is the default, which means always break when hitting the breakpoint.  In Figure 3, I selected the third option, "break when the hit count is a multiple of". If you then change the value from the current value of 1 to 1000, then when that line is hit a multiple of 1000 times (i.e., 1000, 2000, etc.), the program will break. Breakpoint Hit Count
Figure 3 Breakpoint Hit Count

3.  Touch and Go Breakpoints (a.k.a. Trace-points)

Sometimes, in a program, especially those having loops with many iterations (e.g., Mortgage Amortization), you may have added print statements to help understand where your program is going wrong. The output provides a trace of your program - not only are you getting valuable data, but you also know for sure which blocks of code are being executed. The downside, as I am sure you have noticed, is that now you have to:
add the print statements
rebuild your program
fix compiler errors related to the new debug
fix run-time related errors related to the debug (more so in C when using printf)
remember to remove all debug statements and rebuild again after you fix the problem
Your debugger offers a powerful alternative to these time-consuming steps. Instead of adding diagnostic print statements to your code, you can set a breakpoint (conditional or otherwise), and when it is hit, you can print out some results. Let’s modify the conditional breakpoint that stopped on the words beginning with “lap”, so as to print out the words matching this criterion, and then automatically continue execution without stopping. To do this, right click on the conditional breakpoint and select “When Hit…” (see Figure 4). Then in the “When Breakpoint Is Hit” popup, set the Print a message toggle. Now, to continue execution without stopping, check the Continue execution toggle at the bottom left of the popup. Touch and Go Settings
Figure 4 Touch and Go Settings

To view the program debugger output, find and select the Output tab in the IDE bottom portion of the debugger screen (see Figure 5). As the matching criterion is satisfied in the conditional breakpoint, the debugger prints out the found value, and then continues execution without stopping at the breakpoint. Touch and Go Output
Figure 5 Touch and Go Output

While the program is printing out its list of words, if you wish to stop the program after seeing a word, you can hit the pause (Break All) button (see Figure 6). Or, if you wish to always stop execution after printing out the words matching the criterion, then you can just unclick the Continue execution toggle in Figure 4.Pause Program Execution
Figure 6 Pause

Caveat: Sometimes the break will be within a library having no source code. In this case you may see assembly code. One way to get back to familiar grounds of your own code is to hit the Step Out button on the Debug Toolbar (possibly multiple times); or if you think you may be nested to deeply into the library, hitting F5 will get you to your next breakpoint.

4.  Exception Breakpoints

In his book The C++ Programming Language, Special Edition”, Bjarne Stroustrup explains the purpose of exceptions in section “8.3.1 Throw and Catch”:
“The fundamental idea is that a function that finds a problem it cannot cope with throws an exception hoping that its (direct or indirect) caller can handle the problem.”
Now suppose you are involved with a large project; and you are using many functions/methods written by your competent co-workers. But after including some of these functions, your program crashes. So you run the program in the debugger, and you see that an Unhandled Exception popup is displayed: Unhandled Exception PopupYou hit the Break button, and you will be able to see where the exception was thrown.  But, normally, you do handle exceptions, so the above popup will not be available to you.

In general in large applications, there may be many cases where a function throws an exception.  If you have a general try/catch handler, and if your functions are heavily nested, then you may have difficulty in isolating the line of code where the exception was thrown. If you add a breakpoint in your catch block, by this point, the stack has unwound, and you will not be able to examine the conditions that caused the exception to be thrown.

The solution is to change how the debugger handles an exception.

4.1.  Change How the Debugger Handles an Exception

You wish that the debugger will show an exception popup when an exception is thrown even if the exception is handled by your program. Here is how to do this:
From the Debug menu, click Exceptions… (See Figure 7)Exceptions Debug Menu
Figure 7  Exceptions Debug Menu


The Exceptions Dialog Box opens (See Figure 8).  In the Exceptions list, use the list control to select the individual exception or category of exceptions whose handling you want to change. For our needs, checking the “C++ Exceptions” will cause a break on a throw of the user defined exception.Exceptions Dialog Box
Figure 8  Exceptions Dialog Box

Then, when running the program, you should get a First Chance exception popup that gives you a chance to debug the exception. Now, you can hit the Break button and examine the conditions that caused the exception.

4.2.  Adding a User Defined Exception

Alternatively, you can choose to break only on the specific user defined exception. To do this, hit the Add button in the Exceptions Dialog box in Figure 8. In the New Exception popup box (see Figure 9), choose the Type of Exception (i.e., C++ Exceptions) and enter the name of the user defined exception (in this example, the “badword” user defined exception is thrown).Add New Exceptions Dialog Box
Figure 9  Add New Exceptions Dialog Box


Figure 10 shows the case where only the user defined exception, badword, is chosen.Choose User Defined Exception
Figure 10 Choose User Defined Exception


4.3.  Breaking on a User Defined Exception

Since in this contrived example, the word “laptop” will be found and declared as a bad word, the readFile function will throw a badword exception. The debugger reacts to this attempt to throw the exception with the popup showing a First Chance Exception (see Figure 11).Break Options on Exception
Figure 11  Break Options on Exception

By hitting Ignore, you do not throw the exception; you just move onto the next instruction following the throw – the exception is ignored (and you take your chances), and the output is:
pares parse pears rapes reaps spare spear
Now you see the maximum number of 7 words for a single anagram. This worked out Ok only because this exception was contrived – no real problem occurred in the program.

By hitting Continue, you allow the exception to be thrown.
By hitting Break, the Debugger takes control; and you may inspect the cause of the exception.

5.  Run To Cursor (Create a Temporary Breakpoint)

If you are stepping through your code and come to a long-running loop that you want to pass over, you can simply right-click on a line of code after the loop and select the “Run To Cursor” option (see Figure 12). This action creates a temporary breakpoint at the selected line. When this breakpoint is hit, the debugger automatically deletes this temporary breakpoint.Run To Cursor Option
Figure 12  Run To Cursor Option

6.  List of Breakpoints

In larger programs it is not surprising to have many breakpoints. When you close your session, these breakpoints are saved by Visual Studio. When you reopen the debugging session, you can find out where the breakpoints are by selecting the following menu option:
Debug -> Windows -> Breakpoints
You will see a list of breakpoints that were previously set. If you double-click on one, it will take you to the source code. If you right-click on one, you will be able to set conditions on the breakpoint. This table also provides you with a convenient way to disable a breakpoint by unchecking the toggle box.

Closing Remarks

I hope these tips on breakpoints make your life even easier when trying to find that nasty bug. Being able to isolate where a program begins to break down is a good part of the battle. Using breakpoints as described above should remove the need to add debug statements. Perhaps, in the past, when you added debug statements, you had to spend additional time debugging them. No longer will that be the case!

As you get more familiar with the debugger, you may be interested in some additional miscellaneous tips in Part 3 - Watch, Memory, Stack Tips.
7
Comment
Author:phoffric
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
3 Comments
 
LVL 35

Expert Comment

by:torimar
Great series of articles, phoffric, a real pleasure to read.
0
 
LVL 32

Author Comment

by:phoffric
Thanks torimar for your comment. Glad you found it a pleasure to read.
0
 
 

Administrative Comment

by:mbizup
Awarded Editors' Choice

mbizup
EE Page Editor
0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

Join & Write a Comment

The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

Keep in touch with Experts Exchange

Tech news and trends delivered to your inbox every month