Before getting into more advanced techniques for defi ning breakpoints, here ’ s a quick review of the methods for creating a basic breakpoint — one that simply stops the program when en
Trang 1If you like the mini - debugger, you ’ ll probably want to set the On Start Open Mini Debugger setting
in the debugging preferences pane
BREAKPOINTS
Breakpoints are locations in your program where you want the debugger to take control Formally,
a breakpoint is set at a particular address in memory When the CPU ’ s program counter matches the address of a breakpoint — that is to say at the instant before the instruction at that breakpoint ’ s address is to be executed — the CPU stops executing your program and passes control to the debugger
So far you ’ ve created only basic breakpoints The default action of a breakpoint is to halt the execution of your program, hand over control to the debugger, and wait for instructions, but breakpoints are capable of much more
Before getting into more advanced techniques for defi ning breakpoints, here ’ s a quick review of the methods for creating a basic breakpoint — one that simply stops the program when encountered:
Click in the gutter of a source fi le
Right/Control - click in the gutter of a source fi le and choose the Add Breakpoint command
Choose the Run ➪ Manage Breakpoints ➪ Add Breakpoint At Current Line (Command+\) command when the active text cursor is in a source fi le
Use any of the debugger commands to create a temporary breakpoint and start the program running
When you ’ re setting breakpoints graphically, Xcode allows you to set a breakpoint on just about any line of the source fi le A lot of times this doesn ’ t make any sense, but Xcode can ’ t tell that
When you set a breakpoint in a source fi le, you ’ re actually setting the breakpoint at the fi rst executable instruction produced by the source fi le at, or following, the line you clicked Figure 18 - 18 shows three breakpoints set in a source fi le All three of these breakpoints point to the same address location The fi rst one is set on a declaration statement that produces no code, and the second one is set on a completely blank line Only the source code on line 30 produces any executable code in the application Ultimately, you could set a breakpoint on line 28, 29, or 30 with the same results The breakpoint is set at the instruction that implements the switch statement
➤
➤
➤
➤
FIGURE 18-18
Trang 2466 ❘CHAPTER 18 DEBUGGING
In a similar vein, source code that you might not think of as producing code often does A good
example is the closing brace of a C++ function All functions have to return, and the closing brace
of the function body produces code that destroys any automatic objects, pops the stack frame, and
returns to the caller This happens even in void functions Consequently, you can set a breakpoint at
the closing brace of a function if you want to catch the function after the body of the function has
executed, but before it returns to the caller
The concept that this section is trying to express is that there is not always a simple one - to - one
correlation between the source code statements and the executable code with which the debugger
deals The debugger does its best to translate between the two, but inconsistencies do occur Just be
prepared for this and understand what ’ s going on
Breakpoint Types
There are two kinds of breakpoints: source breakpoints and symbolic breakpoints So far, this
chapter has only dealt with source breakpoints Source breakpoints are associated with a particular
line in a source fi le You set and see source breakpoints right in the gutter of the source fi le ’ s
editor pane
Symbolic breakpoints are breakpoints that have been created for a particular symbol — that is, at
the address of a symbol defi ned in the program There are two important differences between a
symbolic breakpoint and a breakpoint set at a line in a source fi le
The most obvious is that you don ’ t have to have the source fi le Using symbolic breakpoints, you
can set a breakpoint at the entry point of any library routine or framework API For example,
you could set a symbolic breakpoint at the free() function Any code that calls the free( )
function would break into the debugger
The other important difference is that the breakpoint address is not associated with a line in a source
fi le You could cut the function from one fi le and paste it into another, and the breakpoint would
still work
You fi nd out how to create symbolic breakpoints shortly
Breakpoints Window
Breakpoint management gets far more interesting when you open the breakpoints window,
shown in Figure 18 - 19 You can do this by choosing the Run ➪ Show ➪ Breakpoints
(Command+Option+B) command — which is also available as a button in many toolbars
The toolbar button has an icon of a window containing a breakpoint (not to be confused with the
other breakpoints button that has a + sign) You can also double - click any breakpoint you see in a
source fi le
Trang 3The Breakpoints window has two panes: a Groups & Files pane containing the Breakpoints smart group and a details pane listing the individual breakpoints It should be noted that this is really just
an abbreviated view of your project window, without the editor pane Everything you can do in the Breakpoints window can be accomplished in the Breakpoints smart group and details pane of your project window
Breakpoint Groups
The Breakpoints smart group has two subgroups Each open project creates a group that contains all breakpoints specifi c to that project The group might be simply named Project Breakpoints, or if multiple projects have been opened you will see a group named for each project When you create a source fi le breakpoint in an open project, it ’ s added to its group These breakpoints are saved (per user) in the project document, so your breakpoints will persist between Xcode sessions
The Global Breakpoints group contains breakpoints that are available to all projects This is particularly useful for complex symbolic breakpoints that you want to use in different projects
Possibly, you could keep breakpoints in a common library that you use in several projects Global breakpoints are saved in your Xcode Preferences
Breakpoint Details
The list in the details pane shows the breakpoints selected in the Groups & Files window, or all the breakpoints contained in a selected group or groups To limit the list of breakpoints to a particular subset, select only that subgroup in the Groups & Files pane To see all of the breakpoints defi ned, select the top - level Breakpoints group
Each breakpoint listed displays an icon, description, enabled check box, location, condition, and continue option By Right/Control - clicking the column header of the table you can optionally choose to display the (normally hidden) Comments, Last Modifi ed, and Hit Count columns You may also hide columns that don ’ t interest you
The icon indicates the type of the breakpoint Source breakpoints have a source fi le icon, and symbolic breakpoints have a 3D cube Source breakpoints are described by the function name and line number within the source fi le, shown in the Location column, where they are set Symbolic breakpoints are described by the symbol of the breakpoint address, possibly with a qualifi er to distinguish between similar symbols The location of a symbolic breakpoint is the library or module where it resides
FIGURE 18-19
Trang 4468 ❘CHAPTER 18 DEBUGGING
The name or address of a symbolic breakpoint is editable — double - click the name to change the
symbol Source breakpoints are not Double - clicking a source breakpoint in the list jumps to that
location in the source fi le This is the complement of double - clicking a breakpoint in a source fi le,
which jumps to that breakpoint in the breakpoint window
The Comments column contains a text fi eld for recording your comments about, or a description
of, the breakpoint If you have a lot of comments, open the Info window for the breakpoint and edit
the comments there The Last Modifi ed fi eld records the last time the breakpoint was altered The
Continue column is explained later in the “ Breakpoint Actions ” section, and the Condition fi eld is
explained in the “ Iffy Breakpoints ” section
A breakpoint ’ s detail line can be expanded to display the its actions, described later in the
“ Breakpoint Actions ” section
Breakpoint Details in an Editor Pane
You ’ ve seen breakpoints in editor panes more than a dozen times so far, but there ’ s a somewhat
obscure command for displaying some details about the breakpoint right in the editor pane, as
shown in Figure 18 - 20
FIGURE 18-20
The View ➪ Message Bubbles ➪ Show Breakpoints command reveals breakpoint bubbles containing
some details about each breakpoint This same command is accessible via the Right/Control - click
menu in the editor pane, also shown in Figure 18 - 20
The enabled, auto - continue, and breakpoint condition can be edited right in the editor pane This
can be particularly handy when using the mini - debugger
Deleting Breakpoints
To delete one or more breakpoints in the breakpoints window, select the breakpoints in the window
and press the Delete key You can also select a group of breakpoints in the Groups & Files pane and
choose the Delete command from the Right/Control - click contextual pop - up menu
To delete a source breakpoint from within a source fi le editor, click and drag the breakpoint out
of the gutter You can also Right/Control - click the breakpoint and choose the Remove Breakpoint
command
Trang 5Enabling and Disabling Breakpoints
The check mark column in the breakpoints list shows whether that breakpoint is enabled You can enable or disable an individual breakpoint by ticking its check box This is synonymous with clicking the breakpoint ’ s indicator in the source fi le Enabled breakpoints are dark blue; disabled breakpoints are light blue
Selecting breakpoints in the Groups & Files pane lets you to enable and disable breakpoints
en masse Select any combination of breakpoints and breakpoint groups in the Groups & Files pane — these commands do not work in the details list Right/Control - click one of the selected items and choose either the Enable Breakpoints or the Disable Breakpoints command from the contextual menu Enabling or disabling a group sets the state of every breakpoint contained in that group
Hold down the Option key and the Enable Breakpoints command turns into the Enable Only These Breakpoints command This command enables the selected breakpoints, and then disables all other project breakpoints This is a quick way of enabling a strategic group of breakpoints you want to focus on while simultaneously disabling all others
You may notice that some breakpoints display a – sign in their enabled check box These are enabled breakpoints that the debugger can ’ t set for some reason.
Examine the debugger console output (covered later) to fi nd out which breakpoints are having problems This is most commonly encountered with symbolic breakpoints that the debugger can ’ t resolve Beyond the obvious reason that the symbol simply doesn ’ t exist in the application ’ s name space, it can also happen when you ’ re using ZeroLink or lazily loaded libraries These
technologies defer the loading and linking of functions until they are actually called, which means that the code for many functions won ’ t be loaded into memory when the program starts executing Until the debugger can turn a symbol name into an absolute memory address, it can ’ t set a breakpoint
Creating Symbolic Breakpoints
To create a symbolic breakpoint, fi rst select the Breakpoints group in which you want the breakpoint created At the bottom of the details pane list is a special placeholder breakpoint with
a border around the name Double - Click For Symbol To create a new symbolic breakpoint, do just what it says, as shown in Figure 18 - 21
FIGURE 18-21
Trang 6470 ❘CHAPTER 18 DEBUGGING
The symbol can be any function name known to the linker This can be a function in your own
application or any system API or library to which your application is linked For C function calls,
just the name of the function is suffi cient If there is any ambiguity, Xcode prompts you to choose
the specifi c symbol that you meant In Figure 18 - 22, a breakpoint is set on the free symbol, and
Xcode wants to know which “ free ” it ’ s referring to
FIGURE 18-22
Objective - C and C++ methods must be expressed in their complete form To set a symbolic
breakpoint at the isPrime: method of the SieveOfEratosthenes class, create a breakpoint for
the - [SieveOfEratosthenes isPrime:] symbol Note that the symbol must have a + or – sign
indicating a class or member method In this example, : indicates that the method takes a single
parameter Just like when you ’ re using the @selector operator, isPrime and isPrime: are two
different methods If the method took a second BOOL parameter, the symbol would be something
like - [SieveOfEratosthenes isPrime:ignoringMap:]
In C++, the symbol should be a complete, fully qualifi ed, prototype of the method If the
NestOfBugs class contained a member function named catchMe that took a single integer as a
parameter, the symbol to use would be NestOfBugs::catchMe( int i ) Unlike the Objective - C
symbol, the name of the parameter is included exactly as it was declared in the class statement gdb
will not fi nd the function without a complete copy of its declaration The return type of a function
is not part of its name
Symbolic breakpoints do not appear as breakpoint indicators in the gutter of the source fi le
editor pane, even if the symbol identifi es a function in your source code Other than the visual
differences, symbolic breakpoints are just like source breakpoints and share all of the same
capabilities and traits
Iff y Breakpoints
One of the fi rst things you ’ ll notice about breakpoints is that they always work Although it might
be gratifying to know that the technology is reliable, you may soon discover that it can be a curse
Trang 7as well Setting a breakpoint in a function that gets called a million times is enough to wear out the button of any mouse if you have to click the Continue button 999,999 times Furthermore, quite often the problem with a loop will be found at the end, not the beginning Placing a breakpoint in the middle of a loop can be a study in tedium
What you really want to do is break at the moment your application is doing something interesting
or suspicious For example, you want to break a loop on its last iteration or just when a parameter
is NULL You can accomplish this by using a breakpoint conditional In the Condition fi eld of the breakpoint, enter any C Boolean expression If the breakpoint is enabled and the conditional expression
evaluates to true when the breakpoint is encountered, the breakpoint stops the program.
Otherwise, the breakpoint is ignored and the program continues to run
Conditional Breakpoint Example
The best explanation is an example The following function calculates a factorial:
static long long int factorial( long long int n ) {
if (n > =1)
n *= factorial(n-1);
return (n);
} int main (int argc, const char * argv[]) {
printf("20! = %lld\n",factorial(20));
return 0;
} You build and run the application, and it produces the following output in the debugging console window:
20! = 0 Clearly, that ’ s not the correct answer You suspect that the problem is when n is small, so you set a breakpoint at the fi rst line of the factorial() function (the line if (n > =1) ) You start the program under the control of the debugger, and it immediately stops in the factorial function The variable n has a value of 20
You click Continue and the program recursively calls factorial again, causing the breakpoint to stop again; this time n equals 19
You can see where this is leading You ’ ll have to restart the application another 18 times before you get to a value of n that ’ s interesting Though 18 isn ’ t so bad, 180 would be, and 18,000 would be ridiculous in the extreme
What you really want to know about is what happens when n is small (2 or less) To fi nd out, you set a breakpoint condition, as shown in Figure 18 - 23 Now the breakpoint stops only when n is less than or equal to 2
Trang 8472 ❘CHAPTER 18 DEBUGGING
With a single breakpoint condition, you ’ ve skipped to the 19th invocation of the factorial function
in a single debugging step Now that you ’ re here, you use the Step Over and Step Into commands
to walk through the next few invocations of factorial and immediately see what the problem
is: When n is 1, the if condition is still true, factorial(n - is called, which returns 0, and the
multiplication zeros out the total
The solution is change the conditional to if (i >
Conditional Expressions
A breakpoint ’ s conditional expression can contain only primitive C statements It can ’ t employ
preprocessor macros or make use of any variables beyond what appears in the variables pane
In other words, it can only evaluate expressions based on what the debugger knows about your
program
As an example, take the C variable char string[MAX_LEN] Assuming MAX_LEN was 100, you could
test to see if the string buffer contained a character near the end of the array using the expression
string[98]!='\0 ' However, you could not use the expression string[MAX_LEN - 2]!='\0 '
because the debugger doesn ’ t normally know about preprocessor macros
If there is a problem with the expression, Xcode displays a warning symbol next to the condition
in the Breakpoints window Sometimes this is normal, because an expression might refer to local
variables that aren ’ t in scope when the condition is defi ned The debugger reevaluates the breakpoint
condition when the breakpoint actually occurs, but if the expression is still invalid, it is ignored and
the breakpoint acts as if it has no condition The debugger also notes the problem with a message
in the debugger console like “ warning: Error parsing breakpoint condition expression ”
FIGURE 18-23
Trang 9Be very careful about expression side effects The expression i==0 activates
executing Assignment, increment, and decrement operations all have their
Be conservative and defensive when you ’ re using expressions Don ’ t make assumptions that will cause your expression to miss problems, or cause more problems itself The following table describes
a few examples:
EXPRESSION RESULTS
i 1000000 Poor The variable is a signed integer If the value exceeds
MAX_INT , the value will be negative and the condition will never be true If you ’ re looking for a problem where this integer exceeds its nominal range of 0 to 1,000,000, this expression could miss it
!(i > =0 & & i < =1000000) Better The range of the integer is bounded at both ends
ptr - > m!=0 Poor ptr is a pointer that could be NULL , causing the expression
evaluation itself to throw an address error
(ptr!=0 & & ptr - > m!=0) Better The member value m will not be tested if the ptr is NULL ,
avoiding possible access errors
(ptr==0 || ptr - > m!=0) Best If you really never expect ptr to be NULL , the breakpoint
should break on that condition as well
If your condition requires something to be computed, consider adding some code to your application
to help your debugging Here ’ s an example that assumes that you have defi ned a DEBUGGING macro and set it to a non - zero value when compiling your code for testing:
#if DEBUGGING int actualStrLen = strlen(str);
#endif strncpy(buffer,str,1024);
You can now set a breakpoint at the strncpy statement with the condition actualStrLen > =1024
Breakpoint Ignore Count
A common breakpoint condition is to simply ignore the next few hits If you hit a breakpoint in
a loop that ’ s going to repeat 1,000 times and you want to know what happens toward the end of the loop, you just want to skip over the next 998 occurrences of that breakpoint This is easily accomplished by setting a breakpoint ’ s ignore count setting
In the breakpoint window, fi nd the Ignore Count column for the breakpoint and enter a non - zero integer The next occurrences of that breakpoint will be ignored To reactive the breakpoint, set the ignore count back to zero
Trang 10474 ❘ CHAPTER 18 DEBUGGING
Breakpoint Actions
In addition to just stopping the program, breakpoints can also perform actions when they are
encountered When a breakpoint is taken, the program stops and control is passed to the debugger
If the breakpoint has breakpoint actions, the debugger immediately performs those actions
To add or edit actions, expose the breakpoint ’ s contents in the Breakpoints window For source
breakpoints, double - click the breakpoint in the gutter of the source fi le and Xcode takes you to that
breakpoint in the Breakpoints window Click the + button to add a new action Click the – button
to delete an action You can ’ t reorder actions, so when you ’ re adding actions, use the + button above
the point where you want to new action inserted
After you ’ ve added an action, choose the type of action from the pop - up menu at the top There are
fi ve kinds of breakpoint actions, as listed in the following table:
ACTION FUNCTION
Debugger Command Executes a command in the debugger
Shell Command Executes a shell command
AppleScript Executes an AppleScript
Log a Message
The Log command enables you to generate a message when the breakpoint occurs How you receive
this message is controlled by the two check boxes in the lower - right corner of the action, shown in
Figure 18 24 Log outputs the message to the debugger console, and Speak uses the Macintosh text
-to - speech technology -to say the message out loud
FIGURE 18-24