Please explain me about this leak

2019-08-20 20:30发布

问题:

I have the following error message in my log:

2011-10-13 10:41:44.504 Provision[386:6003] *** __NSAutoreleaseNoPool(): Object 0x4e0ef40 of class CABasicAnimation autoreleased with no pool in place - just leaking
2011-10-13 10:41:44.505 Provision[386:6003] *** __NSAutoreleaseNoPool(): Object 0x4b03700 of class NSConcreteValue autoreleased with no pool in place - just leaking
2011-10-13 10:41:44.506 Provision[386:6003] *** __NSAutoreleaseNoPool(): Object 0x4b04840 of class __NSCFDictionary autoreleased with no pool in place - just leaking

The error message occur when I run the following code.

CGRect newFrame = [viewTop frame];
newFrame.origin.x = 0;
newFrame.origin.y = 0;
[UIView beginAnimations:@"nil1" context:nil];
[UIView setAnimationDuration:0.3f];
[viewTop setFrame:newFrame];
[UIView commitAnimations];

Any insight? Thank you for your kindness

回答1:

This is happening because you are using autoreleased objects when there is no autorelease pool present. You can read more about NSAutoreleasePool here.

In your cocoa development you may have seen expressions like these:

@"string text"
[NSMutableArray arrayWithCapacity: 42]
[someObject autorelease]

All of these make use of the autorelease pool. In the first two cases, an autorelease message is sent to the objects for you. In the last case, we send it to the object explicitly. The autorelease message says "decrement the reference count when the closest autorelease pool is drained." Here is an example:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSObject *myObject = [[NSObject alloc] init]; // some object
[myObject autorelease]; // send autorelease message
[pool release]; // myArray is released here!

As you might imagine, there can be memory leaks if you autorelease an object expecting the pool to release it later. Cocoa detects this and throws the error you posted above.

Typically in Cocoa programming, an NSAutoreleasePool is always available. The NSApplication's run loop drains it at every iteration. However, if you are doing work outside the main thread (i.e., if you created your own thread) or if you are doing work before calling NSApplicationMain or [NSApp run], there won't be an autorelease pool in place. You can usually fix this by adding one:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
CGRect newFrame = [viewTop frame];
newFrame.origin.x = 0;
newFrame.origin.y = 0;
[UIView beginAnimations:@"nil1" context:nil];
[UIView setAnimationDuration:0.3f];
[viewTop setFrame:newFrame];
[UIView commitAnimations];
[pool release];