1. Trang chủ
  2. » Công Nghệ Thông Tin

Lập trình Wrox Professional Xcode 3 cho Mac OS part 63 pps

7 111 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 7
Dung lượng 1,76 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Select one or more variables in the pane and then choose one of these fi xed formats to force the expression of the value, or values, into the desired format.. Double -click the variable

Trang 1

EXAMINING DATA

Now that you ’ ve learned all about controlling the fl ow of your application while debugging, let ’ s

return to examining the content of variables “ The Variables Pane ” section briefl y introduced the

variables pane of the debugging window Now look at that pane in a little more detail and look at

other ways of examining the contents of memory

To recap, the variables pane (previously shown in Figure 18 - 4) displays the known variables within

the scope of the selected stack frame Variables are grouped by type Structures and objects appear

as groups, forming a hierarchy of containers and values These are described by the debug symbol

information attached to your program

As you step through your program, the debugger compares the values that were displayed when

your program was last started against the values that appear when the debugger stopped it again

Any values that are different are highlighted in red, as shown in Figure 18 - 26 — it may be diffi cult

to see in this black - and - white illustration, but the value of variable j is red

FIGURE 18-26

The code was stopped at line 57 where the value of j was undefi ned The Step Over command was

issued The debugger allowed one statement (the for statement) to be executed and stopped the

program again The value of j is now 4 and Xcode highlights the change in the display Using the Step

Over command again returns the value to black again, because that statement did not alter its value

It doesn ’ t matter how much the program executes between stops As long as the variables pane is

showing the same set of variables at the next stop, Xcode highlights whatever values are now different

Scalar Formats

The Value column displays the primitive value of each variable For scalar values, this is a numeric

value For structures and pointers to structures, it is the address of the structure or the value of the

pointer The default display format for scalar values is Natural For signed integers and fl oating

-point numbers, the column displays a signed decimal value Unsigned integers display an unsigned

Trang 2

decimal number Character types display both the decimal and Unicode representations of the value Pointers and structures are shown as hexadecimal memory addresses The natural format is usually suffi cient, but you can manually choose a different representation The choices are as follows:

Hexadecimal Decimal Unsigned Decimal Octal

Binary OSType You can fi nd these formats in the Run ➪ Variables View menu, or in the Right/Control - click contextual menu of the variables pane Select one or more variables in the pane and then choose one of these fi xed formats to force the expression of the value, or values, into the desired format

Choose Natural to return to Xcode ’ s automatic formatting The fi rst fi ve formats are self - explanatory The OSType format displays a 32 - bit integer as a four - character string This data type is used by many system APIs

Viewing Data in Another Window

You can also choose to examine the contents of a value or structure in a separate window Double -click the variable name, choose the Run ➪ Variables View ➪ View Variable In Window command,

or from the Right/Control + click contextual menu This can be particularly useful for viewing large

or complex objects It is also handy because the variable ’ s value continues to be displayed as long

as the variable exists You can place a local structure pointer in a separate window and continue to examine its value while stepping though other functions After the variable is no longer in scope or its stack frame is released, the window containing the value closes

If a variable type isn ’ t even close to the type of data it represents, you can use the Run ➪ Variables View ➪ View Value As command, also available via the Right/Control + click contextual menu of the variables pane Select a variable in the list and choose this command Xcode prompts you to enter a cast for the variable ’ s value, as shown in Figure 18 - 27

FIGURE 18-27

Xcode then attempts to interpret the value of that variable using the type cast This is particularly useful for generic types such as void* As shown in Figure 18 - 27, the pointer to a string was assigned to a void* variable By using the View Value As command, you can coerce the debugger to interpret the void* value as if it was a char* variable, shown on the right

Trang 3

Sometimes you just need to look at memory Using the Debug ➪ Variables View ➪ View As Memory

command, you can open the memory browser window shown in Figure 18 - 28

FIGURE 18-28

The browser displays a block of memory in hexadecimal and ASCII formats, much like the

hexdump command The Address fi eld determines the starting address of the display Initially,

this is the address of the selected scalar, structure, or object in the variables pane If the selected

variable is a pointer or object reference, the address is the value of that pointer (a dump of what

the pointer points to, not a dump of the pointer ’ s value) The Bytes menu lets you select how much

memory is disassembled in the window Choose one of the preset values or enter your own Use the

up and down arrows between the Address and Bytes fi eld to move one page of memory forward

or backward The Word Size and Columns menus control the number of bytes in each column of

hexadecimal values, and the number of columns in each line, respectively

There is only one memory browser window Selecting a new address using the View As Memory

command simply changes the address in the Address fi eld The Address fi eld has a pop - up menu

that keeps a short history of previously viewed addresses If you need to follow a pointer to another

address that you fi nd in a block of memory, simply copy the address from the hexadecimal listing

and paste it into the Address fi eld (prefi xing it with 0x)

If you try to view memory that is outside the address space of your application, the memory browser

displays A ’ s for the bytes it can ’ t access

Viewing Global Variables

The Globals group in the variables pane contains a selected set of global variables that you want to

examine Normally, this group has nothing It ’ s impractical for this group to contain every global

variable in your application ’ s process space The group could contain hundreds of variables, be

impossible to navigate, and place a huge burden on the debugger display

Instead, the group starts out empty Use the global variables window, shown in Figure 18 - 29, to

add variables to this group or merely browse the global variables in your application You can open

this window using the Run ➪ Show ➪ Global Variables command or by attempting to expand the

Globals group when it is empty

Trang 4

The global variables window is divided between a list of modules on the left and the list of global variables in each module on the right Select a module, and Xcode lists all of the global variables that your application has access to on the right To search for a particular variable name, enter some fragment of the variable ’ s name in the search fi eld at the top of the window

Figure 18 - 29 examines the global variables declared in a program named DataBlock The listing tells you the fi lename the variable is declared in, its current value, and its type By selecting the box

in the View column, this variable is added to the Globals group in the variables pane The viewed global variables are recorded in the user preferences of the project document After these variables are added, they will always appear in the Globals group of your variables pane until they are removed or until the variable itself no longer exists

Expressions

Another way to view variables is through expressions

Expressions appear in the Expressions window, shown in Figure 18 - 30 You can open this window using the Run ➪ Show ➪ Expressions command To add an expression in the window, type the expression

in the input fi eld at the bottom of the window, or select any variable and choose Run ➪ Variables View ➪ View Variable As Expression

These are debugger expressions and are subject to all of the limitations and caveats of breakpoint conditions In the Expressions window, each expression acts like a variable You can alter its display format or open it in a separate window You can also add type casts to an expression to coerce the interpretation of the expression ’ s value

Expressions are interpreted within the context of the currently selected stack frame, and those expressions retain that context In the example previously shown in Figure 18 - 30, there are two expressions that resolve to value of the integer i , but these two variables are from different stack frames Each was added to the window and a different stack frame was selected in the threads pane The fi rst one was added while a function was executing, but that function has now returned

Therefore, the context that defi ned that variable no longer exists and the expression is marked as

“ out of scope ”

FIGURE 18-29

FIGURE 18-30

Trang 5

To delete an expression, select it in the Expressions window and press the Delete key

Expressions are very useful for examining the contents of array values An expression like stack[1]

examines the second element in the stack array The expression buffer[index] examines whichever

element the variable index refers to

DATA FORMATTERS

The summary column in the variables pane is designed to present a compact, informative

explanation of the value or object For some objects, like strings, the summary value is obvious

For objects like a collection it might display the size of the collection — not a lot of detail, but

still informative For an opaque FSRef structure, it might convert that structure into a readable

fi lename — very informative, indeed This descriptive transformation is done using data formatters

Xcode includes many data formatters, but they won ’ t help with any object that you defi ne You can

create your own data formatters to summarize complex data structures and objects in the debugger

Creating a Custom Data Formatter

Creating your own data formatters is very easy It is really nothing more than a format string with

placeholders for values or expressions derived from the variable being summarized Any regular

text in the data formatter is displayed verbatim There are two kinds of placeholders: references and

expressions

References are delimited by two percent characters ( %reference% ) A reference can refer to a single

member variable by name If the variable is contained in a substructure, use the appropriate period

(.) separated variable name You cannot use operators such as pointer dereferences or array indexes

For that, you need to use an expression Taking the class that ’ s defi ned in Listing 18 - 3, the reference

to the integer record_no of DataBlock class would be %header.record_no%

LISTING 18 - 3: Sample class

typedef struct {

int record_no;

unsigned long checksum;

} BlockHeader;

@interface DataBlock : NSObject

{

@public

BlockHeader header;

NSMutableData* data;

}

An expression is any debugger expression; the same kind of expression that you can add to the

Expressions window In fact, it ’ s good to think of an expression in a data formatter as an expression

in the Expressions window, as you ’ ll see in moment

Expressions are contained between matching braces ( { expression ) Unlike references, expressions

do not assume the context of the value being examined To refer to the object being examined, use

Trang 6

the $VAR macro in the expression $VAR will be replaced with the name of the variable when the data formatter is evaluated Using the previous class as an example again, the expression to access the record_no value would be {$VAR.header.record_no} If you ’ re now guessing that you can refer to other variables in the context of the current stack frame, you ’ re correct However, this isn ’ t a good idea, which is explained later Limit your evaluation to the structure or object being examined

The advantage of expressions over references is that they are more expressive You can perform math, include conditionals, and even call member functions Again using the class defi ned in Listing 18 - 3, here are some valid expressions:

{$VAR.header.record_no}

{$VAR.header.checksum & 0x0000ffff}

{$VAR.data?(int)[$VAR.data length]:0}

Combining these two techniques, you can now create a data formatter for the DataBlock object type Start by running the program and stopping the debugger with an instance of the DataBlock class in scope Make sure that Run ➪ Variables View ➪ Enable Data Formatters is checked Select the DataBlock variable in the variables pane and choose the Run ➪ Variables View ➪ Edit Summary Format The debugger lets you edit the data formatter for the variable Now you can enter the data formatter string shown in Figure 18 - 31

FIGURE 18-32

FIGURE 18-31

After it has been entered, this text becomes the data formatter used for every instance of the DataBlock class The debugger resolves the references and expressions for each instance, creating the more informative summary shown in Figure 18 - 32

The syntax used for references and expressions can be extended to obtain other information about the value or expression The fi nal display value can be something different from the value to which the expression evaluates The other types of information that can be extracted from an expression are chosen using one of the column selectors listed in the following table The “ column ”

Trang 7

you are selecting is one of the columns in the variables pane or the Expressions window In essence,

the result of a reference or expression is treated as if it had been entered into the Expressions

window The column selector lets you choose which column in the window will be used as the result

of the expression You can think of an expression result as an object with four properties (value,

name, type, and summary) — the column selector lets you choose which property to display

{ expression }:v ,

% reference %:v

The value of the expression — that is, the primitive numerical value that would appear in the Value column of the Expressions window This is the default column Omitting the column selector is equivalent to using :v

{ expression }:t ,

% reference %:t

The type of the fi nal data object to which the expression evaluates A numerical expression would result in a primitive data type, such as int or double The type of an expression that refers to a member variable, or calls a function, will be the type of the expression ’ s result For example, the expression {[$VAR owner]}:t would display the type of the object returned by the method owner

{ expression }:s ,

% reference %:s

This selector results in the text that would appear in the Summary column

of the expression Because the Summary column can be formed using data formatters, this is a way of using other data formatters in portions

of your data formatter You can only use this on expressions that have a summary display Expressions that result in primitive values do not have any content in their Summary column

{ expression }:n ,

% reference %:n

The name of the variable or expression that would appear in the Expression column of the Expressions window The column is self -referential and not particularly useful

The type column ( :t ) can be useful for displaying the type or class of a member value For

example, if you have a class that manages a collection of homogenous objects, a data formatter

of collection of {[$VAR lastObject]}:t would tell you what kind of objects your collection

contains

The summary column selector is the most useful You can use it to construct data formatters from

other data formatters

To get a feel for creating your own data formatters, look at the following example Let ’ s assume

you have a project with the DataBlock class shown in Listing 18 - 3, and a subclass named

StampedDatablock, shown in Listing 18 - 4

LISTING 18 - 4: DataBlock subclass

@interface StampedDataBlock : DataBlock

{

@private

NSCalendarDate* createdDate;

NSCalendarDate* modifiedDate;

}

Ngày đăng: 04/07/2014, 06:20