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

AID: 3530
  • Status: Published

12231 points

  • Byphoffric
  • TypeTips/Tricks
  • Posted on2010-08-04 at 19:57:07
Awards
  • Community Pick
  • Experts Exchange Approved
Introduction
This article 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 the following link:
As you get more familiar with the debugger, you may be interested in some additional miscellaneous tips in the following article:

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'

                                    
1:

Select allOpen 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-Breakpoint2.PNG
  • 448 KB
  • Condition-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.PNG
  • 5 KB
  • Breakpoint Condition True
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.JPG
  • 20 KB
  • Breakpoint Hit Count
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.GIF
  • 35 KB
  • Touch and Go Settings
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.GIF
  • 19 KB
  • Touch and Go Output
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.GIF
  • 10 KB
  • Pause Program Execution
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-Popup.JPG
  • 15 KB
  • Unhandled Exception Popup
Unhandled Exception Popup
You 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.JPG
  • 22 KB
  • Exceptions Debug Menu
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-Menu-Popup.JPG
  • 30 KB
  • Exceptions Dialog Box
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).
Exception-Add-New.JPG
  • 12 KB
  • Add New Exceptions Dialog Box
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.
Exceptions-Choose-User-Defined.JPG
  • 31 KB
  • Choose User Defined Exception
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).
Exception-Throw.JPG
  • 22 KB
  • Break Options on Exception
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.JPG
  • 30 KB
  • Run To Cursor Option
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 the following article:
    Asked On
    2010-08-04 at 19:57:07ID3530
    Tags

    Visual Studio 2008 Express

    ,

    Debugger

    ,

    Breakpoint Tips

    ,

    C/C++

    Topic

    C++ Programming Language

    Views
    2436

    Comments

    Expert Comment

    by: torimar on 2011-01-21 at 02:15:28ID: 23028

    Great series of articles, phoffric, a real pleasure to read.

    Author Comment

    by: phoffric on 2011-01-21 at 02:39:06ID: 23029

    Thanks torimar for your comment. Glad you found it a pleasure to read.

    Add your Comment

    Please Sign up or Log in to comment on this article.

    Join Experts Exchange Today

    Gain Access to all our Tech Resources

    Get personalized answers

    Ask unlimited questions

    Access Proven Solutions

    Search 3.2 million solutions

    Read In-Depth How-To Guides

    1000+ articles, demos, & tips

    Watch Step by Step Tutorials

    Learn direct from top tech pros

    And Much More!

    Your complete tech resource

    See Plans and Pricing

    30-day free trial. Register in 60 seconds.

    Loading Advertisement...

    Top C++ Experts

    1. jkr

      261,219

      Guru

      1,000 points yesterday

      Profile
      Rank: Savant
    2. sarabande

      121,084

      Master

      3,800 points yesterday

      Profile
      Rank: Sage
    3. Infinity08

      54,855

      Master

      0 points yesterday

      Profile
      Rank: Genius
    4. ambience

      50,164

      Master

      0 points yesterday

      Profile
      Rank: Sage
    5. Zoppo

      48,382

      0 points yesterday

      Profile
      Rank: Genius
    6. evilrix

      48,358

      80 points yesterday

      Profile
      Rank: Genius
    7. satsumo

      22,400

      0 points yesterday

      Profile
      Rank: Guru
    8. tampnic

      19,040

      0 points yesterday

      Profile
      Rank: Master
    9. phoffric

      16,596

      0 points yesterday

      Profile
      Rank: Genius
    10. DanRollins

      16,330

      0 points yesterday

      Profile
      Rank: Genius
    11. duncan_roe

      14,400

      0 points yesterday

      Profile
      Rank: Genius
    12. gtokas

      12,700

      0 points yesterday

      Profile
      Rank: Wizard
    13. AndyAinscow

      12,132

      0 points yesterday

      Profile
      Rank: Genius
    14. mccarl

      9,600

      0 points yesterday

      Profile
      Rank: Wizard
    15. TommySzalapski

      8,800

      0 points yesterday

      Profile
      Rank: Genius
    16. pepr

      7,824

      0 points yesterday

      Profile
      Rank: Genius
    17. kaufmed

      7,168

      0 points yesterday

      Profile
      Rank: Genius
    18. Thommy

      6,700

      0 points yesterday

      Profile
      Rank: Wizard
    19. ubound

      6,550

      0 points yesterday

      Profile
      Rank: Master
    20. kuroji

      6,000

      0 points yesterday

      Profile
    21. for_yan

      6,000

      0 points yesterday

      Profile
      Rank: Genius
    22. mrwad99

      4,600

      0 points yesterday

      Profile
      Rank: Wizard
    23. masheik

      4,572

      0 points yesterday

      Profile
      Rank: Guru
    24. Orcbighter

      4,332

      0 points yesterday

      Profile
      Rank: Master
    25. ozo

      4,300

      0 points yesterday

      Profile
      Rank: Savant

    Hall Of Fame