3

In my iPhone app, I am getting three strange warnings in the console at the very beginning of the app, before any code at all has been called:

*** __NSAutoreleaseNoPool(): Object 0x84be00 of class NSCFString autoreleased with no pool in place - just leaking
*** __NSAutoreleaseNoPool(): Object 0x84b000 of class NSCFString autoreleased with no pool in place - just leaking
*** __NSAutoreleaseNoPool(): Object 0x849c00 of class NSCFString autoreleased with no pool in place - just leaking

I use MBProgressHUD in a number of places to show progress indicators, which is what some of the other discussions of this problem have pointed to because it throws a new thread when displaying the progress indicator. But the strangest thing is that these seem to be thrown before even the beginning of my main() function:

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

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

When I put a breakpoint in my code on the very first NSAutoreleasePool, before that line even runs I get this warning. What could be causing the error when, supposedly, I am not running any of my own code before this point?

Jason
  • 14,517
  • 25
  • 92
  • 153

5 Answers5

5

You likely have a constructor somewhere that is running before main() that is triggering this problem. What libraries are you linking against and/or are you using any __attribute__ directives?


Herp.

Realized something obvious. Since the objects are leaked, they still exist. Set a breakpoint on main() and then, at the GDB prompt, type po 0x84be00 (only replace 0x84be00 with the address of one of the strings that was leaked).

That'll show you the contents of that string and give you a very good clue as to what the cause is.

Derp.

Set a breakpoint on __NSAutoreleaseNoPool and see what the backtraces show you.

I fail at the obvious today (only obvious because I've been down this road 18.27314 million times).

bbum
  • 162,346
  • 23
  • 271
  • 359
  • I am linking against a number of libraries and foundation classes, including: libxml2.dylib, Foundation.framework, UIKit.framework, CoreGraphics.framework, CoreData.framework, libcucore.A.dylib, QuartzCore.framework, SystemConfiguration.framework, Security.framework, MessageUI.framework, CFNetwork.framework, AddressBook.framework, AddressBookUI.framework, AudioToolbox.framework, libteEngine.a (this is for TextExpander Touch support), and libxml2.2.7.3.dylib. How can I check what `__attribute__` directives I am using? – Jason Mar 21 '11 at 02:29
  • If you don't know, you probably aren't using any (they are uncommon). The problem won't be from a system framework (maybe *just maybe* in the simulator). – bbum Mar 21 '11 at 02:38
  • Also, how would I set a breakpoint on __NSAutoreleaseNoPool since it is not actually in my own code? – Jason Mar 21 '11 at 02:51
  • At the gdb prompt, `b __NSAutoreleaseNoPool` would work. Or you can use the breakpoints inspector and create a symbolic breakpoint. – bbum Mar 21 '11 at 03:02
2

You have a static variable somewhere in the app that is being initialized outside the main runloop. Something like:

static UIImage *myImage = [UIImage imageNamed:@"fred.png"];

Look for any static variables that initialize objects, and initialize them in something like applicationDidFinishLaunching to set them up with an autorelease pool in place.

Even though it says an NSString is leaking it could be any kind of object.

Kendall Helmstetter Gelner
  • 74,769
  • 26
  • 128
  • 150
  • I have a number of `static` variables in my code, some in external libraries. Is there a way to test which is the culprit without simply commenting them out one by one? – Jason Mar 21 '11 at 19:59
  • The quickest way is probably to comment out and run - do a few at once and do a binary search for the culprit. The _NSNoAutoReleasePool may work as well (I've had it skip that breakpoint sometimes though). – Kendall Helmstetter Gelner Mar 21 '11 at 21:52
2

In apps using background threads you need to create an autorelease pool within the background method:

-(void)myMethodThatRunsOnBackground:(id)param {
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

  //body of method

  [pool release];
}

answer credit: nobre84 on iphonedevsdk.com

Rocco
  • 91
  • 7
2

I was looking for an answer to this problem, but I managed to work out what the problem was after some research. I too had this error which occurred before main was executed and I tracked it down through me implementing a method called + (void)load which I thought was a great name to load some global class specific data. I did not realise that load was actually already defined and me using it was overriding the default load, and load is executed before main. Thus I was leaking. Renaming it to myload fixed it.

StudentJ
  • 21
  • 1
0

You could try to put a symbolic breakpoint for autorelease to see where and when this is being called.

drewag
  • 93,393
  • 28
  • 139
  • 128