views:

434

answers:

3

When I compile my iPhone project (in the command line), the log output looks like:

2009-11-05 22:19:57.494 xcodebuild[51128:613] warning: compiler 'com.apple.compilers.llvm.clang.1_0.analyzer' is based on missing compiler 'com.apple.compilers.llvm.clang.1_0.analyzer'
=== BUILDING NATIVE TARGET Foo OF PROJECT foo WITH THE DEFAULT CONFIGURATION (AdHoc) ===

Checking Dependencies...
2009-11-05 22:19:58.032 xcodebuild[51128:5b07] *** _NSAutoreleaseNoPool(): Object 0x722d410 of class NSCFString autoreleased with no pool in place - just leaking
Stack: (0x97257f4f 0x97164432 0xfea624 0x2620e34 0x2620cbd 0x2384304 0x23957a3 0x948b76f0 0x948b8d35 0x948ae3c5 0x948aeaa8 0x2620922 0x9716adfd 0x9716a9a4 0x926bd155 0x926bd012)
2009-11-05 22:19:58.035 xcodebuild[51128:5b07] *** _NSAutoreleaseNoPool(): Object 0x720b370 of class NSCFDictionary autoreleased with no pool in place - just leaking
Stack: (0x97257f4f 0x97164432 0x2621454 0x262012a 0x2620e53 0x2620cbd 0x2384304 0x23957a3 0x948b76f0 0x948b8d35 0x948ae3c5 0x948aeaa8 0x2620922 0x9716adfd 0x9716a9a4 0x926bd155 0x926bd012)
2009-11-05 22:19:58.038 xcodebuild[51128:5b07] *** _NSAutoreleaseNoPool(): Object 0x720b370 of class NSCFDictionary autoreleased with no pool in place - just leaking
Stack: (0x97257f4f 0x97164432 0x2621454 0x2620174 0x2620e53 0x2620cbd 0x2384304 0x23957a3 0x948b76f0 0x948b8d35 0x948ae3c5 0x948aeaa8 0x2620922 0x9716adfd 0x9716a9a4 0x926bd155 0x926bd012)
2009-11-05 22:19:58.044 xcodebuild[51128:5b07] *** _NSAutoreleaseNoPool(): Object 0x7111690 of class NSCFDictionary autoreleased with no pool in place - just leaking
Stack: (0x97257f4f 0x97164432 0x2611215 0x2620f50 0x2620cbd 0x2384304 0x23957a3 0x948b76f0 0x948b8d35 0x948ae3c5 0x948aeaa8 0x2620922 0x9716adfd 0x9716a9a4 0x926bd155 0x926bd012)
2009-11-05 22:19:58.078 xcodebuild[51128:5b07] *** _NSAutoreleaseNoPool(): Object 0x7114c10 of class NSCFNumber autoreleased with no pool in place - just leaking
Stack: (0x97257f4f 0x97164432 0x2611242 0x2620f50 0x2620cbd 0x2384304 0x23957a3 0x948b76f0 0x948b8d35 0x948ae3c5 0x948aeaa8 0x2620922 0x9716adfd 0x9716a9a4 0x926bd155 0x926bd012)
2009-11-05 22:19:58.088 xcodebuild[51128:5b07] *** _NSAutoreleaseNoPool(): Object 0x71a28c0 of class NSCFNumber autoreleased with no pool in place - just leaking
Stack: (0x97257f4f 0x97164432 0x2611286 0x2620f50 0x2620cbd 0x2384304 0x23957a3 0x948b76f0 0x948b8d35 0x948ae3c5 0x948aeaa8 0x2620922 0x9716adfd 0x9716a9a4 0x926bd155 0x926bd012)

Then there are a whole bunch of processing commands (a bunch of setenvs), and then the CompileC commands start, some of which (but not all, maybe 10% of them) are followed with more complaints about leaks.

However, it compiles correctly, and runs fine. I ran it with Leaks, and it found two 16 byte leaks that I can't quite track down yet, but nothing on the order of the mess of messages above. And besides, how does it know there's a leak when it's compiling?

A: 

Most programs will run correctly even with leaks, ... but anyway I don't think you are showing enough information. My guess is that you are sending an object autorelease where there is no pool in place?. lol. Did you try Instruments?

nacho4d
+1  A: 

Those warnings might be because of leaks in the tools themselves. But if not, those kinds of messages are what you see if you run in a thread or perform a selector in the background without setting up an autorelease pool.

Dustin Voss
+5  A: 

In short, the compiler is smarter than you think ;). These errors mean that you are autoreleasing various objects (NSString, NSDictionary, NSNumber) in a context that did not allocate an NSAutoreleasePool. For example, the main.m file of a project should declare an autorelease pool:

int main(int argc, char *argv[]) {

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    int retVal = UIApplicationMain(argc, argv, nil, nil);
    [pool release];
    return retVal;
}

In many applications this will be the only pool that is ever allocated. Without this pool you can't autorelease anything, and should you try to autorelease it has no pool to go to so it effectively becomes a leak. Check your main function to make sure you have an NSAutoreleasePool being allocated.

There are other situations where you may want to declare another NSAutoreleasePool. The most common situation is when selectors are invoked in a new thread. Every thread must have its own NSAutoreleasePool. For more information on this see the slide 36 of Stanford University CS193P Lecture 10:

- (void)someAction:(id)sender {
    // Fire up a new thread
    [NSThread detachNewThreadSelector:@selector(doWork:) withTarget:self object:someData];
}

- (void)doWork:(id)someData {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    [someData doLotsOfWork];

    // Message back to the main thread
    [self performSelectorOnMainThread:@selector(allDone:) withObject:[someData result] waitUntilDone:NO];
    [pool release];
}

Another example is an expensive loop where you are autoreleasing many objects. Rather than letting the main NSAutoreleasePool grow to an enormous size, you will find that creating a new NSAutoreleasePool every N times around the loop will help keep your resource use to a minimum. Some of this code was also borrowed from the lecture slides listed above:

int N = 10;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

for (int i = 0; i < someLargeNumber; i++) {
    NSString *string = ...;
    string = [string lowercaseString];
    string = [string stringByAppendingString:...];
    NSLog(@“%@”, string);

    // Release the temporary pool and allocate a new one
    // every N times around the loop

    if (i % N == 0) {
        [pool release];
        pool = [[NSAutoreleasePool alloc] init];
    }
}

[pool release];

Perhaps you have some code like this which is not always allocating or releasing the pools as expected. I'm not sure the compiler is smart enough to notice this type of issue though.

James Wald
I actually *do* have an autorelease pool allocated before my `UIApplicationMain`; however, it's in a file that's already compiled, and I just link to it with this project. So maybe the compiler's being too smart for its own good?
Jesse Beder
Hmmm, this seemed to be the problem. I moved the autorelease pool back into the project, and the warnings went away. I guess it was getting confused.
Jesse Beder
Its possible that its an issue with Xcode itself, I've never tried compiling from the command line so I haven't seen this before. Did you just add the file to your project so you always compile it?
James Wald