Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2003-310
$eventId
ID of event: wwdc2003
$eventContentId
ID of session without event part: 310
$eventShortId
Shortened ID of event: wwdc03
$year
Year of session: 2003
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: ...

WWDC03 • Session 310

Debugging and Tuning Carbon Applications

Apple Developer Tools • 1:02:05

In this session, we demonstrate how the Apple Developer Tools ease Carbon debugging, showing their use in analyzing C, C++, and Objective-C++ code. The Apple IDE's enhanced source-level debugger are featured as well as the power of Mac OS X's low-level GDB debugger. You'll see enhanced visual debugging in action, as well as the power of the command-line-driven GDB debugger. You'll also learn the best ways to use Apple's performance tools to get the most out of your Carbon apps.

Speakers: Chris Espinosa, Chris Nebel

Unlisted on Apple Developer site

Transcript

This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.

Morning, everybody. Welcome to session 310, Debugging and Tuning Your Carbon Applications with Xcode. If you do not want to learn about debugging your Carbon applications with Xcode, now would be an excellent time to deplane. This is actually going to be a little more focused on debugging than on tuning.

Robert Bodich did an excellent presentation on the performance tools yesterday, and I saw three plugs in sessions yesterday pointing to custom data formatters, so I've changed the content a little bit to focus more on the debugging and custom data formatting, because most of the stuff that Robert explained on tuning and diagnostics applies just as well to Carbon applications as to Cocoa applications. So if you missed that, catch it on the DVD. There's some excellent stuff there.

I want to talk about Carbon. It's not just for Code Warrior anymore. We've been designing Xcode so that it's a great Carbon development environment and putting a lot of emphasis on Carbon debugging in the debugging environment. Panther and Xcode have some really great tools built in to help you build and debug your Carbon applications.

What you're going to learn in this session today are some basic differences between the Carbon debugging you may be used to on Mac OS 9 with Mac's bug and the Code Warrior IDE debugger. And what you have in Mac OS X with GDB and the Xcode debugger. There are some techniques for using GDB and Xcode to debug Carbon apps. Some secrets that are hidden on Apple's website in plain sight in a file called Carbon Tips and Tricks. If you haven't read it, that's what I stole most of this presentation from.

Some new features in Xcode that you haven't seen before that aren't on the web that are really cool. That will not only allow you to debug your application, build custom debuggers in your application, but also see a lot of your familiar Carbon data types right in the debugger with no further ado. And then some Carbon specific performance and tuning tricks. I have like one or two slides on those like I said.

Let's go through the steps in debugging and tuning. This should be familiar to everybody. First, you have to define your quality and performance goals. I think if you remember from the Mac OS X presentation, the way we got Safari so fast was that we made no performance regressions a requirement. So if you really want to deliver a performance application, if you really want to deliver a quality bug-free application, all of the tools in the world won't help you if you don't have the methodology and the discipline to make sure that the tools are used in the process.

So everything I'm going to show you today, it's great if you know it. It's even better if you define a process that makes sure that these get used. For example, distributing these custom data viewers throughout your organization or building them into your product build process, rather than having them on a per-engineer ad hoc basis.

You need to prep your project for debugging, and we're going to show you some ways to set up some environment variables and set up some build settings to make your project more debuggable that are Carbon specific. Get your basic functionality working. Run your app in the debugger and isolate bugs.

Then when you get the bugs out, run your app under the performance analysis tools to see if you've met your metrics. And it's really pretty important to make sure that your application works before you really start to use the performance tools on it, because the performance tools far prefer a running application to a broken application. And then you iterate and iterate and iterate.

Your friend is GDB. I know a lot of you don't believe that, but GDB is the underlying debugger in the Mac OS X system, and it's really going to help you out. Debugging without GDB on Mac OS X is like debugging without Mac's bug on Mac OS 9. You can get pretty far with symbolic debugging and with the debugging the IDE shows you, but unless you know what's going on down at the middle level, you'll never really know what's going on with your application.

So if you don't have any familiarity with GDB, you really should acquire some in order to do great debugging on Mac OS X. We're going to show you some of the basics today, and then some of the interactions between the IDE and GDB. The basic way to launch an application in the debugger is from the terminal. You issue the GDB command and then the path to your application, and you need to go into your application and all the way down into the package of your application, the .app/contents/macos, all the way down to the DYLD executable.

So this is people's first mistake is they try to GDB the package, GDB the executable. Second thing you can do is just you can attach to a running application. Launch your application, launch GDB, and then attach to it. So you have two modes: launch it inside GDB or attach to it once it's running.

If you've used any other command-line debugger, the commands are conceptually familiar even though they're probably under different names. B sets a breakpoint. P displays a variable's value, so you have to print variables rather than just type expressions. X examines memory, and that's like DM in MaxBug. C continues execution after a breakpoint, and BT prints a backtrace. If you're used to SC in MaxBug, it's BT in GDB. We're all grown-ups, we can learn new two-letter acronyms.

What's great about GDB is that GDB, while it's stopped in the inferior, lets you evaluate expressions and call functions within your application or within the framework. And this is very powerful, and this is the first technique we're going to show you, is that there are a lot of debug-only functions built into the Carbon framework that let you figure out what's going on in your Carbon applications in ways you wouldn't normally be able to do.

Many of these fulfill roles that were filled by D commands in MaxBug. These are now, instead of being in the development environment or in the debugger, they're built into the framework, and you just invoke them from the debugger. It's a pretty long list, but you can print debug info for HI objects or window groups. You can print the event queue or watch events coming in. You can print the menu lists or menus or menu items or windows. You can even flash the viz region or the update region.

You can even see the time of a window just to see what it happens to be at this point. These are all listed in the Carbon tips and tricks document on the web, which I'll point you to at the end, so you don't have to scribble furiously now and get the parameter list right. But the point is, you can call any of these from GDB while you're paused in your application to see what Carbon thinks your app is doing. So to demo some of these, I'm going to bring up Chris Neville on keyboards.

We're going to start with an application called Appearance Sample, which is on your Xcode CD. This copy of Appearance Sample has been updated to build a native project. And what we're going to do is we're going to invoke it in GDB. We're going to start it off in GDB without using Xcode. It's already been built.

And GDB loads and it runs the application, and there you go. Now, to interrupt a running application from GDB, you just press Control-C, and it stops it. And there we go. We're interrupted. You can do a stack trace, see where you are, things like that. Now we want to ask Carbon what a couple of things are going on. So we're going to make the debug print menu list call.

And we just do call void debug print menu list, paren paren, and we see this is our menu list, according to HIToolbox. There you go. And it shows the menu ref. Chris is now going to do debug print all window groups, and he's going to get a hierarchical list of all the window groups.

It's got the hex address, and it's also got the window group identifier. This will be very helpful in going back to your nib or going back to your code and figuring out what windows have been instantiated at any time. Now he's going to continue the application, go back, open another window.

Go back, interrupt the application again. Print the window list again, and now you see the new window is in the window list. So this is a very helpful debugging technique from GDB to figure out what's going on in your application. We can go back to the slides. Thank you, Chris.

Now, I mentioned a little earlier about preparing your application for debugging. And there's a technique we use inside Apple for the Carbon Framework itself to prepare the debug version of the Carbon Framework, which I'll show you a little bit later, which you can use in any Carbon application. It's built into Carbon. There are two header files called debugging.h and assertmacros.h, which are part of the Carbon Framework.

And if you include the Carbon Umbrella Framework, you've got these macros defined in your application right now. All you need to do is turn them on. Assertmacros.h, if you look at it, is a whole list of asserts you can throw in your application on various conditions. You can verify that things are certain values.

You can verify that things are not values. You can make sure things are conforming, things are non-zero. Large number of macros you can use just to make sure that your data is what you want it to be. And in your production builds, they all fall out and are no-op.

So if you are considering using, constructing a whole set of debug macros that are in your debug builds but fall out in your production builds, we've already built them for you. They're right there in assertmacros.h. All you have to do is define a preprocessor flag, debug, set it to one, and they're invoked. And then there's an additional preprocessor macro that's specified. It specifies the level of debugging. And we define four levels for you.

And they have different degrees of precision and explanation and verbosity on the debug strings. If you set debug internal, that gives you the source file and the line number in which the assertion has been thrown, which is very useful for internal debugging. If you set debug external, it just gives the assert and the name of the string that was associated with the assert, so your users can report that back.

If you have debug break only, then when an assert is thrown, it just breaks into the debugger and doesn't log a message. And then if you say debug production, then all of the asserts are silent. And you can set these either from the command line, either in include files and header files when you build your project, or you can even set them in Xcode. We'll show you a little bit about that later.

There's a second thing, like I said earlier, the debug versions of the Carbon libraries. Every version of every Mako library that we supply in a framework comes in the developer release with two parallel versions, a debug version and a profiling version. And the debug version has perhaps additional calls and certainly additional console logging of what's going on inside that framework.

And if you build and link your application with the debug variant, when you make system calls, then those system calls, if you pass them bad values or if there's a bad condition somewhere in the framework, it will do console spew. This is very, very useful and not enough people do it.

Again, you can control this with an environment variable if you're just running in GDB, or you can control it with a pop-up menu in Xcode, and we'll show you how to do that. One thing about using Xcode, you have to turn off zero link in order to use the debug variants of the library. And that's what we're doing with libraries right now. Okay? And so we'll bring Chris back up again to show you a couple of these things.

So we're going to bring up the appearance sample code in Xcode now, and go to a file called MegaDialog. That's right. Go to the switch pane method. And here's some, there's some crude error checking going on here. This isn't really very useful, you know, if the input value is invalid, then just do nothing.

Maybe we want to see when that input value is invalid, so we're going to put an assert here. Just verify what that value is, and that will cause a log message if the pain index is zero. Now that's all we type here. The verify macro in assert macros does the rest of the work. Now to fire that off, we go to our project settings.

Get the project inspector and go to our build styles, because we want the asserts only in the development build style and not in the deployment build style. So we'll add, by clicking the little plus box down at the corner, an other_cflags. and it moves, so you need to go select it again.

Not that one. That one. And we're going to define the debug macro equals 1 and debug_internal equals 1. And then we're going to build the project. And by defining those, we're going to activate those macros, we're going to define, verify, and it's going to run. Well, not yet. Not yet.

Build errors and warnings. No, no, no, hang on, hang on. Turn off zero, well...

[Transcript missing]

It's not spelled wrong. It's, it's, it's, it's, um... Build errors and warnings window. It's the build dialogue. CleanBuild. It's a development release, folks. GDB is also still running the application. That's okay. Okay.

So now the application is built with the debug flags. He's going to run the application. And when the application runs, you see that the first time we call that, we get an assert that pain index equals 0. It turns out this function is called with pain index equals 0 a whole lot. Now maybe that's a performance problem or a logic problem in our application. Maybe it's not, but by just silently returning, we'd never know.

But by throwing an assert there, we get an interesting log to figure out what's going on. Now you notice a couple other things about this is that it shows you the name third party client. Well, that's the default name. There's another variable that you can declare that's defined in debugging.h that if you assign that preprocessor macro, it actually puts the name of your application, whatever you assign it in there, into your log so you can get better logging messages.

And since we did the debug internal style, we're getting the line number and the source file in which the assert's happening. So these are built in. They're very useful. Now we need to quit the application, and we'll show you building with the debug version of the Carbon Library, which generates a lot more diagnostic output, not just a single assert.

So what Chris is going to do here is go down into the executable configuration, and this configures what happens when we run or debug our application. And you see there's a pop-up menu that says Dynamic Library Runtime Variant, the default standard, and we're going to set it to debug. And that means when we link our application and when we run our application, we're going to link and run it against the debug variant of the library.

So if we build it and run it, and open up the run log. We see a whole lot of output from the Carbon framework of interesting things that this application, this sample application that Apple ships on the Developer CD as an example of how to write code, all of the wrong values that it passes the Carbon framework. So use this as a lesson.

This is really very useful if you want to know what the framework is doing. As you mouse around the application and as we do things, it generates even more asserts. These are asserts using the assert macros and using debugging.h that are built into the Carbon framework that are turned on in the debug variant. Okay? Thank you, Chris.

Now he showed you a little bit of debugging with Xcode. First we started out in GDB, and then we did a little bit of GDB-style text spewing from inside of Xcode. Now we're going to show you a little bit of Carbon debugging interactively with the Xcode debugger. The Xcode debugger is a lot better than the Project Builder debugger was. I hope you saw in a couple of the sessions, like yesterday afternoon, some of the capabilities of it. I'm going to go a little more in-depth into some of the Carbon aspects of that.

Like any other IDE debugger, it shows you the execution threads, it shows you the stacks and the backtraces where you happen to be in the code. It shows you the source code, it shows you the local variables, and it shows you the input parameters of the functions in a way that you can figure out what the values are and what the variables are. It also lets you set and manage breakpoints.

There are some new debugging features in Xcode. We do C++ exception handling where GDB and Project Builder did not. This is going to be very useful if you use C++ exceptions as a routine part of your application structure. We allow you to step through templates. So templates can be really, really gnarly, and if you can't step through them, step through instantiation or use of them, it's really, really hard to figure out what's going on.

We do that now in Xcode. We've got some built-in data viewers for foundation data types and the most important Carbon data types you use, and it's an extensible plug-in architecture where you can define your own, not just for Carbon data types, but for application-specific data types as well.

So now I'm going to hand it over to Chris, and he's going to do his demo of C++ exceptions and the stepping-through templates. Okay. So what we've got here should look familiar to you if you came to session 307. This is the Power Plant appearance demo, kind of the Power Plant version of appearance sample that we've imported into Xcode. So let's just start this debugging. Loads, runs.

Okay, so here it is. Again, just shows off the various controls, various kinds of windows. various kinds of windows. Hmm, this isn't working. It's a bug. How are you going to fix it? How indeed. Okay, so when this particular type of bug happens, I know from experience that it's usually because someone is throwing an exception and it's just being silently swallowed. Now, stuff like this is pretty hard to track down, especially in something like Power Plant, because quite often you didn't write either the code that's throwing or the code that's catching.

However, what we can do with Xcode is we can pause and then turn on Stop on C++ Throw and Stop on C++ Catch. So we'll continue, go back to Appearance Demo, and now, oh, sure enough, So there's the exception itself, and it's coming from this function here, throwIfNil, because I just set it to nil to force an exception.

Power plant tends to not throw exceptions unless something goes seriously wrong, so that was the simplest way to do it. So let's see where that actually winds up. We'll hit Continue, and now we stop in the catch, or actually we stop on the function call that generated the exception, process next event. If we step over, we'll wind up in the catch block itself.

So I also wanted to show off some debugging of standard C++ library stuff and C++ standard template library. And to do that, I actually wrote my own project because Power Plant tends to not use this stuff, which is fair because it was created before they mostly existed. So, what we have here is a fairly simple, stupid STL.

Oh, I knew I was going to forget that. Okay, there's a bug. We're in, and now I have to... You have to turn off Stop on Throw and Catch before you run the debugger, or the debugger won't run. We'll fix that in time for GM. All right, let's try that again.

Okay. So here we are. I've actually already stopped at a breakpoint. This is sort of your, you know, STL 101 application. It sucks a bunch of words out of the system dictionary, uppercases them, and then blats out a few to standard output. So we've stopped right here on a call to four each. I've already got a breakpoint on the function that's going to uppercase everything using transform. So we'll step into that.

Okay, so here we are stopped in uppercase. And, you know, we'd like to see the string that we're operating on. So, well, here it is. It's S. But if we expand it, this is not really what I had in mind. This is not exactly useful. I want to see the string. So, this is what custom data formatters are for.

You've probably seen already how you could use custom data formatters to pick pieces out of a structure, individual fields. But you can also call a function. So, what we'll do here is we'll say var.cstr, because standard library strings have a handy thing that will return a C string. And it's going to think about that for a minute.

Really, this didn't happen when I was practicing. It worked great in rehearsal, folks. It worked fine in rehearsal. What's going on here? Well, this is entertaining. Yeah. All right. We're just going to... Well, while Chris is doing that, we'll go back to slides and explain how the custom data formatters work.

The custom data viewers, if you've seen them yesterday, Chris, let me know when it's working. Yep. The custom data format is, if you've seen them yesterday, a simple functionality that has three levels of implementation. The simple functionality is there's a summary column, and you can type an expression into the summary column, and that expression is evaluated.

The basic syntax, the basic thing you can do is you can extract members from a structure or a class and display them in the summary view, and you can put strings around them, so you can say length equals this member, height equals that member, and that uses this percent sign notation, percent member percent. So anywhere you have a struct or a class or an array, you can use the percent sign notation and get at things inside that structure and promote them to the summary of that structure.

That really helps you look at a variable without having to turn down the turn-down arrow, especially if it's a very large thing. It gets you a lot more data density in your debugger view. The second level is that you can evaluate an expression, and the basic rule is that you can put inside curly brackets in a summary view anything that you can type on the GDB command line and execute.

That means any C or C++ arithmetic expression and any function calls, function calls within your application, method calls on your objects, or system calls to the Carbon framework. This is very, very powerful. Those are evaluated every time that that variable is displayed. So every step, it's going to see if the variable's value has changed, and if it has, it's going to reevaluate that expression.

So you've got to be a little careful about this, because it's going to be reevaluated very, very frequently. So don't make your expressions too complex or too lengthy to execute, and make sure you don't call anything with side effects, for example, because this is actually executing in the context of your application, in your application's process space, in your application's memory space, and anything that this application does can affect, anything this expression does can affect your application.

There are a couple of utility variables that you can use in this expression. $var is the thing itself, the thing that's being evaluated. So you can just do, you know, curly brace $var. and then get at members of it, or you can call methods on that by $var arrow or whatever.

And then for convenience, $parent, if you're viewing a class member or a struct member, $parent, if you're viewing a class member or a struct member, $parent, if you're viewing a class member or a struct member, that $parent is its owner. So if you're drilling down inside something, but you need reference to a sibling, for example, you can do that by $parent and then referring off the sibling, or you can get at information in the parent itself. That's very useful.

The third thing that you can -- are you ready? Sort of. Okay. If we can go back to Chris's machine, we'll show -- Okay, so I still haven't been able to get the custom data formatters to work, but what I will show you is the third thing, which is stepping through template code.

So we're stopped here in our own function, and you'll notice that we were called from four each. Oh! So... Wait, wait, wait, Chris. What? I've got it. You do? Remove the custom data formatter I threw in right before the demo from the custom data formatters folder and try again. You bastard.

Really folks, I was trying to improve the quality of experience of the demo. Oh, okay, where is it? We'll show you how to install custom data formatters. Library folder. Application Support, Apple, Developer Tools, Custom Data Views, C-List Plugin.Bundle, yeah, just drag those to the trash. Quit and reopen Xcode and try again.

I was up here until five minutes before the presentation started trying to debug something that many of you requested yesterday. I want to show you. I'll show you the source code, but I'm not going to show you it working because it crashes Xcode. Okay, so let's try this again. So we stopped in transform. We want to see the actual value of this string. So let's see if this works this time. var.cstr, function call. Aha, now it works.

Mayor Cooper, Mayor Maxima Cooper. Okay. So that's all fun. So now, like I said, we were actually called from 4Each, so we'd like to see what's going on up one level. So let's remove this breakpoint so we don't keep hitting it. And if we just step out, ooh, template function. And we can just-- Step through this.

Now, again, we've got sort of a similar problem here, except this one is even more complicated. I'd like to see the thing that first points to. This is an iterator, and again, this is another obscure structure that has all sorts of weird bits that I really don't understand. But custom data formatters can deal with these too, even though it's a template type. So let's see. Starvar.

And there it is. So we can see this changing and getting uppercased as we step through the loop. Thank you. Okay, back to the slides please. So we've shown you the two kinds of custom data view formulas. First, the simple member access, and then second, the function call. And the function calls are very powerful. They can work within your application. They can work on template types. They can work on C++ classes. They're really powerful. But there's one more thing that's even more powerful, so powerful that it'll bring down Xcode if you do it wrong.

[Transcript missing]

So here's a simple example of one. This is the custom data viewer for-- this is the actual code of the data viewer for a Carbon handle inside the Carbon data viewer's package. There are really two parts to this. One is the plist entry, and the other is the library code. And in the top is the plist entry. All you see-- it's basically the invocation of the library code, the bundle code, with the variable and the ID. And that's all.

Very straightforward. And then the library code-- the first two lines are to get me access to my callbacks. There's a special variable called PBXGDBPluginFunctions that when Xcode debugger loads my plugin, it plugs in a pointer to an array of callback functions into that static. And then I jump through that in order to get to my callbacks. And then you see my function, the data viewer's Carbon handle, expects to get a handle and the ID.

It checks to see whether the handle's valid, because I don't want to do anything like jumping through zero if I don't have to. And if it is, then I essentially Sprintf through this function to print the size of the handle by calling getHandleSize, which is usually pretty safe. Then I check the Hget state and mask it against the lock bit, and depending upon the state of that, I Sprintf lock or unlock.

So this way, whenever I see a handle in my debugger data viewer, I get its size and its state of whether it's locked or unlocked. And if it's null or the handle is invalid, then I get invalid. So this is a very simple data viewer. And we have built in a lot of these for the foundation classes, and we have built in a lot of these for Carbon classes. And if Chris is willing to come up again, Then he's going to show you some of these, again in Appearance Sample, which has a little more support for these things. So we're going to bring up Appearance Sample in the debugger.

and he's going to set a breakpoint and I think that we figured out proxy-dialog.cp line 106? and I think we're getting... - Continue, that's the assert. - Okay. That's the assert we introduced in the first step. Just keep continuing. If you are bugged by asserts, stop it and I'll show you how to turn this off. You have this turned on.

So, stop? Right. Project-- no, go to Executables, turn down Executables, Appearance Sample, double-click, scroll down-- yeah. No, double-click. You were there. Scroll down. Break on calls to debugger debugster. Uncheck that box. And that makes your certs not break in the debugger. We gave them something additional, unplanned. There you go. OK, so go find proxydialog.cp.

And go to line 106. It should be a command key to go to a line. which is invalid now for some reason. Yeah, I used to know what it was. Well, it says it's Command-L, but it doesn't let you do it right now for some reason. Yes, now it does. Focusing problem. 106. And hey, we've got a breakpoint there. Great, that's all we need. So then go back to the application. And we're going to pull up Window Proxy and click the Add Proxy FS spec. And pick a file, any file, don't tell me what it is.

That's fine. That's. And we should hit our breakpoint in the debugger. There we go. Now, notice a couple of things. FS, the file spec variable, the summary is the name of the file. That's very useful. Turn down the file spec and see what you could see otherwise. Well there's the V refnum and the parent ID. Those are nice.

But the name, it's a str_255. Or it's a str_64 which is not a str_255, which we haven't wired up. But just turning it up and seeing just the name and the file spec, that's very nice. See also, err is no error. Just change that to like -39 or something.

And now it says EOF error. So it'll show you what your errors are. Like I said, it knows all 1,900 errors that are in the Carbon headers, and that's through a 1,900-case switch statement. But the next thing, though, you know that Nav Services returns your file spec in an AE desk.

Well, isn't this interesting? Look at the file spec desk, and it says it's a type FSS. Okay? So it tells me what type the desk is right at the top. Now, if I turn it down, it'll show me that it's a type FSS, and that's the contents of it. Yeah.

When you turn down AEDesk, it goes and gets the data out of the AEDesk and then displays it in that line, but it only does that when you turn it down, so it's not expensive unless you really want to see the contents. And it does this with the $parent variable I told you about earlier. It goes back to its parent to get its descriptor type, which is not an OS type, it's an int, unfortunately, so it doesn't show up as a four-character code.

But you also see unused keyword down at the bottom, if you could select that, Chris. That's an OS type, and instead of showing up as a long decimal or a hex number, it shows up as four characters in the variable view. That's something we've put for Carbon debugging in Xcode for you. Okay? So that's custom data viewers.

If we have a little time at the end, I'll show you how to construct a data viewer bundle that crashes Xcode, because that's what I've got to show you right now. And we're working on some better samples for this to post on the web. But what we've implemented in the Carbon data viewers is all of the file types, alias, FS spec, FS ref. We've implemented the AEDesk types.

We've implemented inspectors for all of the opaque HI toolbox references. Window shows you its name and position. Menu shows you its title. HI object shows you what kind of HI object it is. And then we've implemented the file types. We've implemented the identifier. We've implemented basic supports for the Carbon events that shows you the event class and the event name. For Apple events, the same thing, the event class and the event name, if it's a known Apple event and the four character code, if it's not.

And just a whole bunch of things. All the date time things show up as date times instead of 64-bit decimal numbers. So I think you'll find when you're debugging in Xcode, your familiar Carbon data types show up as the values. You think of them as rather than the value that GDB thinks of them as. And I think you'll find that that's very powerful. Okay, back to the slides, please.

Now I spoke a little about Carbon events and a little bit about Apple events. Now Carbon events and Apple events are large things. They're large and they're complex, and we couldn't fit them into single lines in the debugger display. There are some things that you can do when debugging a Carbon application to see what's happening with your Carbon events and with your Apple events, other than just to see the class and the particular event type.

Right now, they're accessible only via the GDB-style interface because they stream a lot of text. We're going to try to find a way to integrate that experience better, to do a little better logging of it, but for now I want to give you some pointers on how to do this. There's a function for Carbon events called setEventTraceEnabled. That is, once again, it's one of these GDB calls from the GDB command line into the Carbon framework.

And that gives you exhaustive information on what Carbon events are happening. There's some similar things that you can do. There's environment variables you can set to turn on and off Apple event debugging, and we'll show those too. Those are done with environment variables rather than with the call. And the output of both of these goes to the standard I/O window, which is available in the console drawer and also available, highly recommended you do this, as a separate window in the Xcode environment. As I said, for Apple events, there are two environment variables you can set.

AEDebugSends will print out any event that you send, and AEDebugReceives will print out any event that your application receives. There are also some functions you can call from GDB. If you want to see a full AEDesk rather than just the summary, if it happens to be a custom one of yours, GDB.printAEDesk will print that desk. And if you want to know more about this, we've even put in a function called GDB.printHelpDebuggingAppleEvents, which spools some help text to standard out. And then you can read that and follow the instructions in it. So let's show you those.

Are we still in Appearance Sample? Yep. We should remove those breakpoints. Already done. Great. And have you set up the AEDebugReceives environment variable? Partly. There it is. An environment variable you can either set up in the shell before you launch your application in GDB, or you can set it here in the Xcode API.

Just create it, check the box, set the value, and then when your application is launched, the shell that launches that application has that environment variable set. That makes it very convenient. So we're going to run this application again, and the first thing we're going to do is to throw an Apple event at it.

And my favorite way to throw Apple events at an application is by using AppleScript. I'm going to show the run log first, so we get to see when it shows up. Clean, pristine, empty run log. Now Chris has written a simple AppleScript here. I'm sure you had to hit the books to learn how to do this.

And he's going to run the script, and he's going to send-- Hmm. That's the error we expected, but we're not-- The error is expected. The absence of the run log is not. Is not. No, not underscore. I did turn this on. "Did you have any problems running against the debug version?" "We didn't in rehearsal." We'll try that suggestion. Fine, we'll show you the Carbon spew. Or that... He's going to turn on a debug, just to make sure.

Send the Apple event. And still no joy. I can't tell you what I broke this time, but it's obviously not your fault. It worked in rehearsal. It worked in rehearsal. All right. Okay. There it is. Is that? Oh. No, it's there. It's just not in the run log. Oh. Oh, it's not in the run log. Chris, it's in standard I/O. Show STD I/O.

There it is. Oh, okay. My mistake. We were looking in the wrong place. It was there all the time. So here are all the multiple events that Chris was sending to the application. And when he turned on AE debugging, it gives you even more information for what handlers it's looking for, what tables it's looking for the handlers in, and what order it's looking for them in. So if your Apple event handlers are firing in an unexpected order, or the wrong ones are firing, turn on AE debug 1 in your environment variables, and this information is logged to the output.

This is very useful if you've got a scriptable application in figuring out what Apple script sends you or what other applications send you in terms of events. And once again, it comes up in the standard I/O log, just like it says on our sheet right here, not in the run log.

Another thing that comes up in the standard I/O log is the Carbon debugging, Carbon Events debugging spew. So what Chris is doing now in the little GDB terminal window is he's calling setEventTraceEnabled It's just parin parin, but I guess... No, it's not. It's not? You tested it? Okay.

We'll talk about that later. So now that he's set the event tracing enabled, when we go back to the application, and start doing things that cause Carbon events to get sent. We see a large amount of diagnostic information about what Carbon events are being sent to whom and when, with what arguments, who's handling them, and what happens as a result of it.

Sending event, called handler, event was handled, leaving target, send event to event target entered. It is more information than you probably need. But if you are trying to debug your Carbon events, this is the first tool to use because it shows you explicitly step-by-step everything that is happening.

Okay. And I think that that's all for the demos.

[Transcript missing]

But I hear you say, but I like CodeWarrior IDE debugging. Well, this is a lot more valid, because CodeWarrior IDE has a lot more windows that do useful and interesting things. Interestingly enough, when you're debugging Mac OS with CodeWarrior, it's using GDB for a lot of the underlying machinery to step and to control the execution flow of the application, though it's using its own functions to get the symbolics information and to display the variables and stack traces. These debugging entry points are available from CodeWarrior expressions, too. So all the things that we've showed you from the GDB command line, those are available from the CodeWarrior IDE debugger as well, if you happen to be using that.

And if you like Zone Ranger for Memory Diagnostics tool, well, you know, Zone Ranger really is great for debugging heap zones, and heap zones are just not that relevant in Mac OS X anymore. In order to really understand what's going on in Mac OS X memory management, it's less of a static looking at what's happening in my heap zone, and more of a dynamic looking at who's calling Malik and when, and are these things getting released in time, and by whom, and on what threads. And some of the Mac OS tools like Malik Debug and like Sampler's Memory Allocation Viewer, those are much, much more relevant to debugging Mac OS X memory problems than static views of your heap like Zone Ranger and Is My Heap Fragmented or Has My Heap Been Stepped On are.

Memory diagnostics with Carbon, you know, new pointer and new handle just get down and call malloc. So if you debug with malloc, you're debugging new pointer and new handle. That's really the important thing to remember. Your handles are just not going to move around, so this whole class of problems that you used to do on Mac OS 9, they just don't exist anymore on 10.

Your low-level memory handling code is not going to be called because until you hit that 4-gig barrier and on a G5, not even then, you're not going to be asked to compact your heap. It's just not going to happen. Your big problem will be leaks, scribbling on your own allocations, you know, getting a wrong pointer somewhere, and trying to use something after you've freed it. And those are things that the malloc debug tools and the sampler tools are really good at doing.

So let's summarize. We've gone through a lot of stuff on Carbon debugging. You've seen the C++ exception handling, the throw and break on throw and break on catch. You've seen stepping through templates and using custom data views in order to see the contents of templates, which is very useful. You've seen some built-in Carbon and foundation data viewers that show you your Carbon data types in a very familiar way.

You've seen how to build your own either with a simple member access or with a complex expression or even with a bundle of code that you write yourself and drop in to do your own custom data viewers. We hope that you'll be able to use some of these tools in debugging your Carbon applications.

We will be down in the Van Ness room to help you get up on Xcode and get your projects on Xcode so you can take advantage of some of these tools. We'll be there for the rest of the day. And we're going to bring. Up God for did you go. We've got actually a lot more to talk about before I call up God free because I've got 18 minutes and I'm not going to let you be bored.

We've got a lot in Xcode right now in the developer release. In the 1.0, the features you've seen are going to be polished, and they're not going to crash, and they're going to be a little more robust. That's what 1.0 is about. We know what you need. We know you need a more flexible type-viewing system. We get very spoiled by using the Code Warrior view-anything-as-any-type system, and by the Code Warrior memory viewer.

That's our aim. We're working on it. It won't be in the 1.0, but it should be in the next release after that. That's certainly on our list. Getting these tracing tools to debug more voluminous things, getting them built into the IDE so you don't have to spool them out to another text window and then scroll through it, that's another priority.

We're going to work on that to find a better integration of those tools. Of course, we can never step or view too quickly. We've got the problem now of the more data you want. You want to see the slower you step, and so there's a tipping point there between fidelity of data and speed of stepping.

One of the things you can do is you can turn off custom data views while you're stepping and then turn it on again in order to look at the values. That, we've found, is a useful compromise. And then watchpoints and event points. We know those are very important to you. We're working on those. You can do those at the low-level GDB command line. We're working on bringing them up into the IDE interface.

[Transcript missing]

The Reference Library. Go to the CD set and see the presentation from last night on basic debugging to go deep into the generic debugging capabilities of GDB. Go to the Debugger Services reference in the Carbon Performance Directory. There's a lot of information on debugging with GDB, GDB internals.

The GDB release notes are always very helpful. Quinn's tech note is very helpful. And here's the Carbon Tips and Tricks document. It's at developer.apple.com/carbon/tipsandtricks. html. It's a very long document with a lot of things, including all of those APIs, the names we called, to print out diagnostics from the Carbon frameworks. It's a very, very useful technical note.

If you haven't used it before, the Chud Toolkit is an incredibly useful set of tools for doing machine-level, instruction-level debugging of what your performance profile of your application is. There have been a couple of demos so far this week, and you can go back to the DVD set and watch those. Or on your Developer Tools CD, open up the Chud Tools package and install them, and just see what miracles they can show you in your code.