Archive for the 'Xcode' Category

Xcode: Sometimes a return is not a return (emacs brain damage)

Sunday, December 23rd, 2012
ExpectedExpression
Indention and Insertion Prefs

Every now and then, I’ll be coding along merrily in Xcode and I’ll get an error much like the one at left. Or “expected identifier or ‘(‘” is another variant.

Huh? That code is fine. Maybe it is an invisible character? Nope. Nothing shown.

Took a bit, but I figured out the cause; 25 years of using emacs as my command line editor of choice, along with the folks at NeXT that implemented the AppKit’s text editor.

In emacs, you quite commonly navigate about by holding down the ctrl- key and banging on various keys to go to the beginning/end of lines, etc. Many of these control sequences are honored by Cocoa’s text editing system and quite a few more are supported in Xcode’s editor.

Seemingly unrelated, ctrl-return is mapped to Insert Line Break.

Thus, if you are an emacs head and you commonly hit ctrl-e<return> to start a new line of code and you happen to hold down the return key just a tad too long, it causes the error shown (or a variant depending on where the insert happens).

The easiest way to tell if this is the case is to go to the line of code after the line reporting the error and hit ctrl-a. If the cursor ends up at the beginning of the previous line, that line is ended by a line break and not a true newline. (ctrl-n – backspace – return to quickly fix).

While it is easy enough to fix once you know the ctrl-a trick, a better fix is one that makes it such that it’ll never happen again.

To do that, go to Xcode’s Key Bindings Preferences, click on “Text”, and scroll down to Insertions and Indetions. On Insert Line Break, delete the ctrl-return (hat + u-turn arrow) key sequence. For convenience add the same to Insert Newline.

Problem solved.

retainCount is useless.

Sunday, December 18th, 2011

The retainCount method just isn’t very useful as has been indicated in the answers to about a zillion StackOverflow questions.

The documentation has this to say:

Important: This method is typically of no value in debugging memory management issues. Because any number of framework objects may have retained an object in order to hold references to it, while at the same time autorelease pools may be holding any number of deferred releases on an object, it is very unlikely that you can get useful information from this method.

Makes it pretty clear that you shouldn’t be calling retainCount, but it really doesn’t illuminate exactly how useless the method is outside of a very narrow context.

So, let us count the ways:

  1. The absolute retain count of an object may change at any time once an object has been passed through any system API.
  2. Any subclass of any system provided class counts as “through system API”; the retain count may be impacted by implementation details.
  3. The retain count never reflects whether an object is autoreleased.
  4. Autorelease is a per-thread concept whereas retain counts are global; race condition derived hilarity can easily ensue.
  5. The retainCount method can never return 0.
  6. Some classes are implemented as singletons some of the time.
  7. Some classes may internally manipulate their retain count directly (I.e. no swizzle for you!).
  8. While retain/release are effectively thread safe, there is always a race between calling retainCount and having the actual retain count change in some other execution context.

Bottom line: the only time the absolute retainCount can be conclusively used for analytic purposes is if you have the backtrace of every retain and release that contributed to the current retain count’s value (there is another use case, documented at the end). If you have that, then you don’t need the retain count and, fortunately, Instruments is already generally quite adept at producing a per-object inventory of retains and releases for you (see Analyzing Data with the Allocations Instrument“.

In general, you should consider the retain count as a delta. Your code causes the retain count to increase and decrease. You don’t +alloc an object with a retain count of 1. Instead, you +alloc an object with a retain count of +1. If you want that object to go away, you need to do something — release, always and eventually — that causes the retain count to be decremented by 1.

It really is that simple.

Almost.

Concurrency — whether through threading or GCD — throws a bit of a wrench in the works (as it always does). Namely, the retain count should really be considered as a per concurrency context delta. If thread or queue A wants to do something with object X, it should hold a +1 retainCount on X for the duration of said operation. One subtle detail that will bear repeating later; an autorelease‘d object does not contribute to thread safety. That is, if thread or queue A wants to pass X to thread or queue B, there must be an explicit retain in A that is balanced by a release (or synchronization event back to A) in B.

Now, some of the enumerated claims may either seem specious at best or, certainly, not obvious as to exactly how it undermines the validity of the retain count. Read the rest of this entry »

When is a Leak not a Leak? Using Heapshot Analysis to Find Undesirable Memory Growth

Sunday, October 17th, 2010

The other day, I was in need of a Cocoa application that launches quickly that has a standard document model. At random, I chose the rather awesome Hex Fiend. As I often do, I also had top -u -o pid running in a Terminal window.

And I noticed something odd. As expected, the RPRVT of Hex Fiend was growing on each cmd-n. However, the RPRVT was not decreasing the same amount every time I hit cmd-w.

That ain’t right. Or it might be. Beyond evidence that a memory use problem may exist, top is a horrible tool for determining if a problem is real or what the actual problem might be.

In this case, the issue looks like a simple memory leak. Hex Fiend is allocating and retaining some set of objects, but not releasing them. The easiest first step is to use the leaks command line tool:

% leaks "Hex Fiend"
leaks Report Version:  2.0
Process:         Hex Fiend [3435]
Path:            /Volumes/Data/Applications/Hex Fiend.app/Contents/MacOS/Hex Fiend
Load Address:    0x100000000
Identifier:      com.ridiculousfish.HexFiend
Version:         2.0.0 (200)
Code Type:       X86-64 (Native)
Parent Process:  launchd [122]
Date/Time:       2010-10-16 20:47:09.935 -0700
OS Version:      Mac OS X 10.6.4
Report Version:  7
Process 3435: 22980 nodes malloced for 2600 KB
Process 3435: 0 leaks for 0 total leaked bytes.

OK; whatever the problem is, it isn’t “leaked” memory in the traditional definition of “leaked memory”.

That is, whatever memory is being allocated and never released is still being referenced somewhere. Maybe a circular retain. Maybe something that has a weak reference from the rest of the App’s object graph such that leaks can’t detect.

In other words, this isn’t just a simple memory leak and it will require more advanced tools to fix.

Read the rest of this entry »

PyObjC Xcode Templates now in Subversion

Monday, December 3rd, 2007

Ronald and I realized that the Xcode templates that are included in Leopard didn’t make it into the PyObjC repository.

So, I moved ‘em over.

You can find them in the PyObjC subversion repository.

These aren’t just templates, though. See the README.txt.

As it implies, the project-tool.py script is used to effectively convert between Xcode templates and buildable projects. That is, you can create a project that builds/runs like a regular Xcode project, and then easily turn it into a template with the invocation of a simple command line like this:

project-tool.py -k -v --template Cocoa-Python\ Document-based\ Application/CocoaDocApp.xcodeproj/TemplateInfo.plist \
    Cocoa-Python\ Document-based\ Application/ \
    ~/Library/Application\ Support/Developer/Shared/Xcode/Project\ Templates/AA\ Testing/Cocoa-Python\ Document-based\ Application

Or, specifically:

./project-tool --help
Usage: project-tool.py [options]  

    Copies tree of templates or projects from  to .
    Before copying, it cleans up  by removing various bits of garbage.
    After copying, it transforms  by replacing strings with their Xcode
    template counterparts.

    The reverse flag can be used to reverse this process; turning an Xcode
    template into a working project.

Options:
  --version             show program's version number and exit
  -h, --help            show this help message and exit
  -v, --verbose         verbose
  -k, --kill-dest       erase  (no warning)
  -r, --reverse         reverse transformation (template -> editable project)
  -w, --working         try to make destination into a working project
  -n, --nib             rewrite NIB files to 10.5 text-only format
  -t TEMPLATEFILE, --template=TEMPLATEFILE
                        path to TemplateInfo.plist that should be used during
                        conversion

Nothing remotely Python specific about it. And, as some have noticed, the PyObjC Cocoa templates leverage the new Interface Builder file format (xib) such that all kinds of substitutions happen in the templated interfaces, too. As in: No more MyDocument ever again.

Xcode 2.3 is now available.

Tuesday, May 23rd, 2006

Xcode 2.3 is now available.

Beyond fixing a boatload of bugs and numerous performance improvements, Xcode 2.3 adds DWARF as a native symbol format. DWARF yields a significantly higher fidelity debugging experience, especially for complex C++ code, while also reducing the memory requirements of the linker.

Full release notes available on Apple’s developer tools web site.

Xcode 2.3 also includes a new distributed build subsystem called Dedicated Network Builds. The preferences pane is a bit fragile — don’t poke at it too hard — but the underlying technology is some neat stuff.

While DistCC remains as the solution of choice for ad-hoc builds on small networks, Dedicated Network Builds [DNB] focuses on accelerating large projects where a farm of machines can be dedicated as builders. In particular, DNB shines with large C++ projects.

Behind the scenes, DNB distributes compilation jobs from your local machine — the recruiter — to the builder machines — the volunteers — using a set of daemons to connect everything together. On the recruiter, a daemon monitors the filesystem to ensure that changes made to the filesystem will cause the remote volunteer caches to be invalidated in an appropriately minimalist fashion.

The volunteers execute the jobs against a mirrored copy of the recruiter’s local filesystem, source, headers, compiler and all. As such, the only dependency between your local machine and the builders is that they are both the same architecture (ppc or i386) and they are running very close to the same version of Mac OS X (i.e. 10.4.5 will be compatible with 10.4.6, but not 10.3.9).

A great deal of effort went into ensuring that cache management wouldn’t swamp the recruiter’s network connection. There is still a hefty cache warmup hit, but the volunteers have the ability to resolve cache misses amongst themselves as well as resolving cache misses against their own local filesystem, when possible.

As one can imagine, there is considerably more to this technology than is described above.

Unit Testing and Code Coverage in Xcode

Saturday, October 29th, 2005

Chris Hanson and I both intended to write something like this someday. Now we don’t have to.

Go read this article about unit testing and code coverage. Specifically, Chris gives detailed instructions on how to integrate gcov based code coverage into Xcode while also leveraging Xcode’s support for unit testing.

Excellent article. Thanks for writing it, Chris. I hope you don’t mind if I file a couple of bugs against Xcode to remind us to integrate something like what you have done sometime in the future.

Advanced Breakpoints

Wednesday, October 12th, 2005

Chris Hanson discusses Xcode’s advanced breakpoints today.

One very important feature of the advanced breakpoints found within Xcode is the ability to cause something to happen in the debugger — play a sound, print some data, run some AppleScript or invoke a shell script — without interrupting the application being debugged beyond stopping it briefly to take whatever action is specified in the breakpoint.

For debugging stuff like drag-n-drop, mouse tracking, and other human-computer-interaction related functionality, being able to break, take action, and continue the application without de-activating the application or otherwise messing with the context of event processing is absolutely critical.

In modern applications, the challenges of debugging are often not about which line of code is broken, but a matter of figuring out which of the 100,000 executions of a particular line of code is broken. Worse, the line of code is generally going to be invoked along one of many paths, often further convoluted by the code’s presence within a class hierarchy such that invocation is determined by state or customization applied by subclasses.

printf style debugging is often derided as an amateurish approach to figuring out what is going on. And it does suck. But it is often the only way to really figure out what is going on.

Until now. I’m finding that I will configure a breakpoint to log-and-continue. Once I figure out what offensive value is at the root of a problem, I can easily configure the breakpoint to no longer continue and to only stop when that value is present.

End result; no more stop/print/continue by hand with the debugger constantly futzing with the event processing context of the application.

Very, very useful.

Job Openings on the Xcode Team

Thursday, July 21st, 2005

We have a bunch of open positions within the Xcode team. If you or anyone you know is interested, has the skills, and wants to work at a truly awesome company (seriously — working at Apple is a blast), please send a resume/CV my way and apply for the job through the official channels which can be found by clicking the links below.

The list with very brief descriptions. Click through for more information.

2373705: Senior Embedded Systems Engineer Help to improve support for iPod development within the Xcode tool-chain.

2374115: Performance Analysis Tools Engineer Improve the integration and capabilities of the performance analysis tools included with Xcode.

2374098: Embedded Systems Performance Engineer Embedded systems (iPod) focused improvements to the performance analysis tools included with Xcode.

2375392: Distributed Build Engineer Help to improve the distributed build feature within Xcode.

2374092: Build Systems Engineer Focused on improving the build system within Xcode. This is not about building Xcode itself, but about refining the code that is run when a developer hits the Build button while running Xcode.

2371488: Xcode Engineer — Xcode UI The Xcode team is seeking an experienced engineer with excellent end user application human interface design skills to conceive, design and develop future enhancements to Xcode and its supporting tools.

The following isn’t with the Xcode team, but may be of interest to folks interest in contributing to development tools.

2371718: Interface Builder Engineer Help to improve and extend Interface Builder.

PyObjC 1.3.7 Released

Wednesday, July 6th, 2005

PyObjC 1.3.7 has been released.

It includes:

  • Initial port to Mac OS X for Intel
  • Xcode 2.1 compatibility
  • Support for SenTestingKit and SecurityFoundation frameworks
  • Complete wrappers for DiscRecording framework
  • … a handful of other bug fixes …

Full details can be found in the NEWS file.

Xcode, file references & build locations

Sunday, December 5th, 2004

Within Xcode projects, every file or resource has a reference that instructs Xcode how to find the file. This includes files, resources, build products, dynamic libraries and everything else in the project.

These references are both extremely powerful and quite easy to configure incorrectly. Any resource reference can be either via a relative or absolute path. If relative, it can be relative to one of several locations including the project, the enclosing group, or the build directory.

Now, Xcode also has a very useful feature that allows you to specify a location into which all build products and intermediate products will be written. First and foremost, this will eliminate the noise of the build directory from your workarea. No more “? build” noise from CVS or Subversion. If you point it to the fastest hard drive on your system, you will also gain the advantage of all the intermediate and final products being written to and read from that fast device. If you have a boatload of RAM, create a RAM drive and eliminate a huge chunk of disk I/O from the build process. If using FileVault, moving the build directories will eliminate the overhead of encrypting the files created during the build of the project (with the obvious security sacrifice).

Just make sure you get the resource references correct. In particular, If you have multiple targets and then have a copy files build phase that copies those targets’ products into the product of some other target, make sure you use a build directory relative reference.

A project relative reference will work, but only on your system and only if your build directory never moves relative to your project directory.

And that is the real challenge to resource references. Misconfigured references will work on your machine the first time you set them, but will fail if used in an environment without exactly the same set of paths.

To help minimize the problem:

  • Use Xcode’s preferences to set the intermediate and final build product directories to some place other than the project. Don’t use the same path. I have often set the path to /tmp/build-bbum/intermediate and /tmp/build-bbum/products respectively. This also guarantees that the projects will be rebuilt after any reboot. Occasional clean rebuilds often seem to clean up weird issues.
  • Create a second user account on your system and use Fast User Switching to occasionally bop over, update a workarea and build the project. This will also rapidly pick up revision control problems, such as forgetting to add a resource to the repository.
  • Better yet, keep a workarea on a second machine or have a friend do an update and make sure things still build.

This came up because I had been playing with Growl and had checked out the source because I wanted to fix a few bugs. The CopyFiles build phase in the GrowlHelperApp were project relative, but referred to build products, thus assuming that the build directory is always in the same place relative to the project.