< Previous PageNext Page > Hide TOC

Viewing Variables and Memory

This chapter describes the various ways in which you can view the values of variables as you debug your programs.

In this section:

Setting the Variable Display Format
Using Data Formatters
Monitoring the Value of an Expression
Browsing Memory
Viewing Shared Libraries


Setting the Variable Display Format

You can view the value of a variable in a variety of formats, including hexadecimal, octal, and unsigned decimal. To display the value of a variable in a different numeric format:

  1. Open the Debugger window and select the variable in the Variable list.

  2. From Run > Variables View.

    choose one of these options:

    • Natural

    • Hexadecimal

    • OSType

    • Decimal

    • Unsigned Decimal

    • Octal

    • Binary

You can also cast a variable to a type that’s not included in the menu. For example, a variable may be declared as void *, yet you know it contains a char * value. To cast a variable to a type, select the variable, choose Run > Variables View View Value As.

Using Data Formatters

Xcode allows you to customize how variables are displayed in debugger datatips and the Variable list in the debugger by specifying your own format strings for the Value or Summary columns. In this way, you can display program data in a readable format. Xcode includes a number of built-in data formatters for data types defined by various Mac OS X system frameworks. You can edit these format strings or create your own data formatters.

To turn on/off data formatters, use:

Xcode menu bar: Run > Variables View > Enable Data Formatters

Important: If you are debugging heavily threaded code, where more than one thread is executing the same code, data formatters may cause threads to run at the wrong time and miss breakpoints. To avoid this problem, disable data formatters.

Writing Data Formatters

You can provide your own data formatters to display data types defined by your program. To edit the formatter associated with a variable value or variable summary, select the variable in the Variable list in the debugger and double-click in the appropriate column of the Variable list in the debugger. You can also choose Run > Variables View > Edit Summary Format.

Data formatters can contain:

Note: Double quotation-mark characters in data formatters must be escaped, as in the following example:

{(NSString *)[$VAR valueForKey:@\"name\"]}:s

Memory management in data formatters: Xcode automatically allocates and deallocates the memory data formatters use. But if a data formatter returns a reference to data that resides elsewhere, the formatter would be responsible for managing that memory.

However, there’s no mechanism to notify data formatters when they are no longer used, therefore, data formatters should not return dynamically allocated memory. They can, however, return static strings; for example, "invalid value".

C++ data formatters: Your data formatters may take C++ pointers but not C++ references. With references, copies of the referenced objects are generated, which may cause undesired side effects.

Data Formatter Example

The following example uses the CGRect data type to illustrate how you can build format strings using member references and expressions. (Note that because Apple provides format strings for the CGRect data type, Xcode already knows how to display the contents of variables of that type). The CGRect data type is defined as follows:

struct CGRect { CGPoint origin; CGSize size; }; typedef struct CGRect CGRect;

Assuming that the goal is to create a format string that displays the origin and size of variables of type CGRect, there are many ways you can write such a format string. For example, you can reference members of the origin and size fields directly. Of course, each of these two fields also contains data structures, so simply referencing the values of those fields isn’t very interesting; the values you want are in the data structures themselves. One way you can access those values is to include the full path to the desired field from the CGRect type. For example, to access the height and width of the rectangle, in the height and width fields of the CGSize structure in the size field you could use the references %size.height% and %size.width%. A sample format string using these references might be similar to the following:

height = %size.height%, width = %size.width%

You could write a similar reference to access the x-and y-coordinates of the origin. Or, if you already have a data formatter for values of type CGPoint that displays the x and y coordinates of the point in the Summary column of the Variable list—such as (%x%, %y%)—you can leverage that format string to display the contents of the origin field in the data formatter for the CGRect type. You can do so by referencing the Summary column for CGPoint, as in the following format string:

origin: %origin%:s

When Xcode evaluates this format string, it accesses the origin field and retrieves the contents of the Summary column for the CGPoint data type, substituting it for the reference to the origin field. The end result is equivalent to writing the format string origin: (%origin.x%, %origin.y%).

You can combine this format string with the format string for the size field and create a data format string for the CGRect type similar to the following:

origin: %origin%:s, height = %size.height%, width = %size.width%

For example, a rectangle with the origin (1,2 ), a width of 3, and a height of 4 results in the following display:

origin: (1, 2), width=3, height=4.

You can also write a data formatter to display the same information using an expression such as the following:

origin: {$VAR.origin}:s, height = {$VAR.size.height}, width = {$VAR.size.width}

When Xcode evaluates this expression for a variable, it replaces $VAR with a reference to the variable itself. Of course, using an expression to perform a simple value reference is not necessary. Another example of an expression in a format string is {(NSString *)[$VAR name]}:s to display the name of a notification, of type NSNotification.

When you specify a custom data formatter for a variable of a given type, that format string is also used for all other variables of the same type. Note, however, that you cannot specify a custom format for string types, such as NSString, char*, and so on. Custom data formatters that you enter in the Debugger window are stored at:

~/Library/Application Support/Developer/<Xcode_release>/CustomDataViews/CustomDataViews.plist

In addition to supplying custom format strings to display variables in the debugger, you can also write code that constructs descriptions for variables displayed in the debugger. These functions can be packaged as a bundle that is loaded into the process being debugged. These functions can then be invoked from data formatters.

Monitoring the Value of an Expression

Using the Expressions window, you can view and track the value of an expression. For example, you can track a global value or a function result over the course of a debugging session. To open the Expressions window, choose Run > Show > Expressions.

Type the expression you wish to track in the Expression field. Xcode adds the expression, evaluates it, and displays the value and summary for that expression. The display format of the value and summary information is determined by any data formatters in effect.

The expression can include any variables that are in scope at the current statement and can use any function in your project. To view processor registers, enter an expression such as '$r0', '$r1'.

In the debugger you can add a variable to the Expressions window by selecting the variable in the Variable list and choosing Run > Variables View > View Variable As Expression.

To remove an expression from the Expressions window, select it and press Delete.

Tips on using the Expressions window: 

Browsing Memory

When execution of the current program is paused, you can browse the contents of memory using the Memory Browser. To open the memory browser, shown in Figure 7-1, choose Run > Show > Memory Browser.


Figure 7-1  Memory Browser

The memory browser window

You can also open the Memory Browser to the location of a particular variable:

  1. In the debugger, select the variable.

  2. Choose Run > Variables View > View As Memory.

In the Memory Browser, you can see:

Viewing Shared Libraries

You can see which libraries have been loaded by the inferior using the Shared Libraries window, shown in Figure 7-2. To open this window, choose Run > Show > Shared Libraries.

The Module Information table lists all the individual libraries the executable links against. In this table, you can see the name and address of each shared library, as well as the symbols the debugger has loaded for that library. The Starting Level column shows which symbols the debugger loads by default for a given library when the current executable is running. The Current Level column shows which symbols the debugger has loaded for the library during the current debugging session. When an entry has a value in the Address and Current Level columns, the library has been loaded in the debugging session.


Figure 7-2  Shared Libraries window

The Shared Libraries window

The path at the bottom of the window shows where the currently selected library is located in the file system. You can quickly locate a particular library by using the search field to filter the list of libraries by name.

Using the Shared Libraries window you can also choose which symbols the debugger loads for a shared library. This can help the debugger load your project faster. You can specify a default symbol level for all system and user libraries; you can also change which symbols the debugger loads for individual libraries.

For any shared library, you can choose one of three levels of debugging information:

You can specify a different symbol level for system libraries and user libraries. User libraries are any libraries produced by a target in the current project. System libraries are all other libraries.

By default, the debugger loads only external symbols for system and user libraries, and automatically loads additional symbols as needed. Turning off the “Load symbols lazily” option, described in “Debugging Preferences” in Xcode Workspace Guide, changes the default symbol level for User Libraries to All. This is a per-user setting and affects all executables you define. You can also customize the default symbol level settings for system and user libraries on a per-executable basis, using the Default Level pop-up menus in the Shared Libraries window.

For some special cases—applications with a large number of symbols—you may wish to customize the default symbol level for individual libraries when running with a particular executable. To set the initial symbol level to a value other than the default, make a selection in the Starting Level column. While debugging, you can increase the symbol level using the Current Level column. This can be useful if you need more symbol information while using GDB commands in the console. Clicking Reset sets all of the starting symbol levels for the libraries in the Module Information table to the default value.



< Previous PageNext Page > Hide TOC


© 2009 Apple Inc. All Rights Reserved. (Last updated: 2009-01-06)


Did this document help you?
Yes: Tell us what works for you.
It’s good, but: Report typos, inaccuracies, and so forth.
It wasn’t helpful: Tell us what would have helped.