Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 16 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
16
Dung lượng
4,32 MB
Nội dung
If 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 Breakpoints ❘ 465 c18.indd 465c18.indd 465 1/22/10 12:55:22 PM1/22/10 12:55:22 PM Download at getcoolebook.com 466 ❘ 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. c18.indd 466c18.indd 466 1/22/10 12:55:22 PM1/22/10 12:55:22 PM Download at getcoolebook.com Breakpoints ❘ 467 The 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 c18.indd 467c18.indd 467 1/22/10 12:55:23 PM1/22/10 12:55:23 PM Download at getcoolebook.com 468 ❘ 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. c18.indd 468c18.indd 468 1/22/10 12:55:24 PM1/22/10 12:55:24 PM Download at getcoolebook.com Breakpoints ❘ 469 Enabling 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 c18.indd 469c18.indd 469 1/22/10 12:55:25 PM1/22/10 12:55:25 PM Download at getcoolebook.com 470 ❘ 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. I 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 c18.indd 470c18.indd 470 1/22/10 12:55:31 PM1/22/10 12:55:31 PM Download at getcoolebook.com Breakpoints ❘ 471 as 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. c18.indd 471c18.indd 471 1/22/10 12:55:32 PM1/22/10 12:55:32 PM Download at getcoolebook.com 472 ❘ 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 - 1) is called, which returns 0, and the multiplication zeros out the total. The solution is change the conditional to if (i > 1) . 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 c18.indd 472c18.indd 472 1/22/10 12:55:32 PM1/22/10 12:55:32 PM Download at getcoolebook.com Breakpoints ❘ 473 Be very careful about expression side effects. The expression i==0 activates the breakpoint when the value of i is zero, and ignores the breakpoint if it is any other value. The expression i=0 sets the value of i to zero and continues executing. Assignment, increment, and decrement operations all have their normal effect on values. Be careful of expressions like o[++k]!=NULL that alter the value of k when the debugger evaluates them. The equivalent expression without side effects would be o[k+1]!=NULL . 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. c18.indd 473c18.indd 473 1/22/10 12:55:33 PM1/22/10 12:55:33 PM Download at getcoolebook.com 474 ❘ 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 Log Logs a message to the system console. Sound Plays a sound. 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 c18.indd 474c18.indd 474 1/22/10 12:55:38 PM1/22/10 12:55:38 PM Download at getcoolebook.com [...]... lastObject]; } Download at getcoolebook.com c18.indd 476 1/22/10 12:55:42 PM Breakpoints 27 28 29 30 31 32 33 34 35 ❘ 477 return (freshView); } - (void)recycleView:(QuickView*)staleView { [pool addObject:staleView]; } @end While testing your program, you discover a problem The correct order of use should be: 1 2 3 4 Create a bunch of QuickView objects Configure their content using -setValues: Display the... Create two breakpoints in ViewPool.m at lines 27 and 32 Add a breakpoint action to the breakpoint at line 32 Set the action type to Debugger Command, and enter the following gdb command: break QuickView.m: 13 3 Add a breakpoint action to the breakpoint at line 27 Set the action type to Debugger Command, and enter the following gdb command: clear QuickView.m: 13 4 Build and start the program under the control... points in the program Another clever trick is to use Mac OS X’s screen capture tool (screencapture) to take a snapshot of your display at a critical moment The Shell Command action takes a command fi le and a list of arguments This must be an executable command fi le — a binary program or an executable script You can enter the path directly, or click the Choose button to browse for it The path can be an absolute... breakpoints may not appear in Xcode because Xcode didn’t create them; but they’re fully functional breakpoints nevertheless Using the debugger command action requires an understanding of the gdb debugger commands and their syntax Documentation for the gdb debugger is available online at http://www.gnu.org/software/gdb/documentation/ Download at getcoolebook.com c18.indd 477 1/22/10 12:55: 43 PM 478 ❘ CHAPTER 18... would get better performance if you loaded a few of these view objects from the nib document, and then reused them again later, so you create a simple pool of view objects: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 @class QuickView; @interface ViewPool : NSObject { @private NSMutableArray *pool; } - (QuickView*)view; - (void)recycleView:(QuickView*)view; @end @implementation... selection Choose the Export Breakpoints command to export the selected breakpoints to a text fi le The Import Breakpoints command creates a new subgroup with the name of the breakpoint export file and populates it with its contents Rename and reorganize the imported breakpoints as you see fit As a single developer, you can use these commands to archive a collection of breakpoints for some future purpose or... begins to reveal itself This action enables a breakpoint to execute almost any other gdb command There’s a lot of potential here, but some all-time favorites are the print, backtrace, and breakpoint commands Two gdb commands that you should never use in a breakpoint action are jump and continue Using jump or continue can interfere with Xcode s ability to execute other breakpoint actions See the “Breakpoint... AppleScript commands like display can’t be used Commands like delay, beep, and say work just fi ne The script can also contain gdb expressions enclosed between @ characters Breakpoint Continuation The earlier example of using breakpoints to set breakpoints glossed over a serious problem The breakpoints with the actions will still break After the breakpoint has been hit, and all of its actions have been... manner of debug automation and checking possible There are, however, some hazards Debug actions are executed asynchronously That is, the debug action merely starts the action The debugger does not normally hang around waiting for them to complete, so be careful about creating breakpoints that will start, or queue up, hundreds of breakpoint actions This can be particularly annoying when you’re using... breakpoints How do you send those breakpoints to your team members so that they can reproduce the problem and fi x it? Project breakpoints are saved on a per-user basis in the project, so you can’t just give them a copy of the project document When they load the project, they won’t see any of the project breakpoints you’ve set And scrawling breakpoint descriptions on napkins doesn’t sound particularly efficient . getcoolebook.com Breakpoints ❘ 477 27 return (freshView); 28 } 29 30 - (void)recycleView:(QuickView*)staleView 31 { 32 [pool addObject:staleView]; 33 } 34 35 @end While testing your program, you discover. reactive the breakpoint, set the ignore count back to zero. c18.indd 473c18.indd 4 73 1/22/10 12:55 :33 PM1/22/10 12:55 :33 PM Download at getcoolebook.com 474 ❘ CHAPTER 18 DEBUGGING Breakpoint. expression string[98]!=' ' . However, you could not use the expression string[MAX_LEN - 2]!=' ' because the debugger doesn ’ t normally know about preprocessor macros. If there