In iOS, when the autoreleasepool create and be destroyed?
When a touch event created, the runloop create an autoreleasepool.
When the touch event ends, the autoreleasepool will be destroyed.
Is my understand of the autoreleasepool right?
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
how can I understand the autoreleasepool in main method?
In xcode 4 we have to create pool and we have release it by using this syntax with NSAutorealeasePool:
{
NSAutorealeasePool *pool=[[NSAutorealeasePool alloc] init];
[pool drain];
}
When ever use like this in Xcode 4 memory is initialized for your pool and control enter into your pool deallocate your pool objects by using drain ..if u use drain means u permanently destroy ypur pool objects..if you use release means its not completely destroyed..
In xcode 5 we are using #autoreleasepool syntax like this:
#autoreleasepool
{
}
Here we don't need to create pool and release the objects..every thing done by compiler..once control enters automatically create the pool and release the pool objects means which we want to deallocate
The NSAutoreleasePool class is used to support Cocoa’s reference-counted memory management system. An autorelease pool stores objects that are sent a release message when the pool itself is drained.
IMPORTANT
If you use Automatic Reference Counting (ARC), you cannot use autorelease pools directly. Instead, you use #autoreleasepool blocks. For example, in place of:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Code benefitting from a local autorelease pool.
[pool release];
you would write:
#autoreleasepool {
// Code benefitting from a local autorelease pool.
}
#autoreleasepool blocks are more efficient than using an instance of NSAutoreleasePool directly; you can also use them even if you do not use ARC.
Few things to keep in mind -
Case 1)
#autoreleasepool
{
MyObject *obj = [[MyObject alloc] init];
//No need to do anything once the obj variable is out of scope there are no strong pointers so the memory will free
}
case 2)
MyObject *obj //strong pointer from elsewhere in scope
#autoreleasepool
{
obj = [[MyObject alloc] init];
//Not freed still has a strong pointer
}
Related
I read the Apple doc about the function of #autoreleasepool. It says in a new thread, the programmer should declare a new autorelease pool using the following code in ARC.
#autoreleasepool{
//etc
}
But as my test, I did not add the #autoreleasepool block in my code, it still run well.My code is like below.
[NSThread detachNewThreadSelector:#selector(threadTest) toTarget:self withObject:nil];
- (void)threadTest
{
// #autoreleasepool {
for (int i=0; i<1000000; i++) {
NSNumber *num = [NSNumber numberWithInt:i];
[NSString stringWithFormat:#"%#",num];
}
// }
}
I used the Xcode Leaks instruments to see whether it has any memory leaks, but I did not find any memory leaks. So the result is that "It seems it is not required to declare the #autoreleasepool block in a secondary thread", is my word correct, can someone clarify this?
Here's a code snippet that illustrates the problem
__weak id ptr = nil;
__weak id ptr2 = nil;
#autoreleasepool {
void (^block)(void) = [^{
NSLog(#"hahaha");
} copy];
block();
[[(id)block rac_willDeallocSignal] subscribeCompleted:^{
NSLog(#"block will dealloc");
}];
ptr = block;
int blockRetainCount = CFGetRetainCount((__bridge CFTypeRef)block);
NSObject *obj = [[NSObject alloc] init];
[obj.rac_willDeallocSignal subscribeCompleted:^{
NSLog(#"Obj dealloc");
}];
ptr2 = obj;
int objRetainCount = CFGetRetainCount((__bridge CFTypeRef)obj);
NSLog(#"oK");
}
NSLog(#"after pool %# %#" , ptr, ptr2);
When I run this snippet, I will see Obj dealloc printed to the console but not block will dealloc. After the autorelease pool also I will see ptr still containing a valid refence to the block while ptr2 has been correctly reset to nil as expected. Why is there this difference? When do blocks get dealloc'ed at all?
Multiple problems that should convince you to not ever try such a thing:
One, CFGetRetainCount isn't guaranteed to return anything meaningful in the presence of ARC.
Two, there is no guarantee that a block uses retain counts at all. Blocks that don't capture any variables are allocated as static variables; copy, retain and so on do nothing at all to them, and they are never allocated or deallocated.
Third, there is no guarantee that any block will ever call dealloc when it is deallocated. And no guarantee that it will happen in the next OS or iOS version.
After running my thread for a while, Instruments shows that __NSDate has steadily incementing its # living value.
My conclusion is that this tread does not dealocate objects. This line, however, causes compilation error NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
How can I force this thread to retain all its objects or how shall I create a proper thread with working ARC.
- (void) start {
NSThread* myThread = [[NSThread alloc] initWithTarget:self
selector:#selector(myThreadMainRoutine)
object:nil];
[myThread start]; // Actually create the thread
}
- (void)myThreadMainRoutine {
// stuff inits here ...
// Do thread work here.
while (_live) {
// do some stuff ...
[runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.05]];
[NSThread sleepForTimeInterval:0.05f];
}
// clean stuff here ...
}
The autoreleased objects are probably the reason for the increasing memory usage,
but you cannot use NSAutoreleasePool with ARC. Replace
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// ...
[pool drain];
with
#autoreleasepool {
// ...
}
Update: You actually need two autorelease pools in your case. First of all, the
Threading Programming Guide states:
If your application uses the managed memory model, creating an
autorelease pool should be the first thing you do in your thread entry
routine. Similarly, destroying this autorelease pool should be the
last thing you do in your thread. This pool ensures that autoreleased
objects are caught, although it does not release them until the thread
itself exits.
And the last sentence gives the clue why you need another autorelease pool: Otherwise
all autoreleased objects created in the long-running loop would only be released when
the thread exits. So you have
- (void)myThreadMainRoutine {
#autoreleasepool {
// stuff inits here ...
while (_live) {
#autoreleasepool {
// do some stuff ...
[runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.05]];
[NSThread sleepForTimeInterval:0.05f];
}
}
// clean stuff here ...
}
}
- (void)myThreadMainRoutine {
#autoreleasepool {
// stuff inits here ...
// Do thread work here.
while (_live) {
// do some stuff ...
[runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.05]];
[NSThread sleepForTimeInterval:0.05f];
}
// clean stuff here ...
}
}
objc[1655]: Object 0x2314e0 of class __NSCFString autoreleased with no
pool in place - just leaking - break on objc_autoreleaseNoPool() to
debug
objc[1655]: Object 0x2315e0 of class NSPathStore2 autoreleased with
no pool in place - just leaking - break on objc_autoreleaseNoPool() to
debug
objc[1655]: Object 0x2316b0 of class __NSCFData autoreleased with no
pool in place - just leaking - break on objc_autoreleaseNoPool() to
debug
File:MultiFormatReader.mm Method:+[MultiFormatReader load] --
objc[1655]: Object 0x2317e0 of class __NSCFString autoreleased with
no pool in place - just leaking - break on objc_autoreleaseNoPool()
to debug
objc[1655]: Object 0x231800 of class __NSCFData autoreleased with no
pool in place - just leaking
- break on objc_autoreleaseNoPool() to debug
..++++++++
File:main.mm Method:main -- mark..
File:BarcodesAppDelegate.m Method:-[BarcodesAppDelegate
application:didFinishLaunchingWithOptions:] -
File:BarcodesAppDelegate.m Method:-[BarcodesAppDelegate
application:didFinishLaunchingWithOptions:] -
This is the relative code:
+ (void)load {
MPLog(#" ..++++++++");
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[FormatReader registerFormatReader:[[[self alloc] init] autorelease]];
[pool drain];
}
int main(int argc, char *argv[]) {
MPLog(#"mark..");
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
This my debug message,I used zxing framework in my APP,But I found before main() method execute, some other code executed already. Why? generally speaking, what executes before main()?
What does this program " objc[1655]: Object 0x2314e0 of class __NSCFString autoreleased with no pool in place - just leaking - break on objc_autoreleaseNoPool() to debug" mean?
Move the 2 MPLogs below NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];?
+ (void)load {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
MPLog(#" ..++++++++");
[FormatReader registerFormatReader:[[[self alloc] init] autorelease]];
[pool drain];
}
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
MPLog(#"mark..");
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
Set a symbolic breakpoint at objc_autoreleaseNoPool to halt execution when this error is encountered. Then you can determine where you need to place your autorelease pools (explicitly).
generally speaking, what excutes before main()?
from +[NSObject load] docs:
Invoked whenever a class or category is added to the Objective-C
runtime; implement this method to perform class-specific behavior upon
loading.
+ (void)load
Discussion The load message is sent to classes and categories that are both dynamically loaded and statically linked, but only if the newly loaded class or category implements a method that can respond.
The order of initialization is as follows:
All initializers in any framework you link to.
All +load methods in your image.
All C++ static initializers and C/C++ __attribute__(constructor) functions in your image.
All initializers in frameworks that link to you.
In addition:
A class’s +load method is called after all of its superclasses’ +load methods.
A category +load method is called after the class’s own +load method.
In a custom implementation of load you can therefore safely message other unrelated classes from the same image, but any load methods implemented by those classes may not have run yet.
I'm seeing this same problem. If I put a breakpoint at objc_autoreleaseNoPool, on the main thread, I get the following useless stack trace:
0 0x332097b8 in objc_autoreleaseNoPool ()
1 0x331fe7b8 in (anonymous namespace)::AutoreleasePoolPage::autoreleaseSlow(objc_object*) ()
2 0x332098de in _ZL22_objc_rootAutorelease2P11objc_object ()
3 0x331fcdb6 in _objc_rootAutorelease ()
It seems to be hitting the autorelease error before anything in the application has actually started. Could this be the result of some load methods in one of the frameworks I have included in the project?
I've noticed that there is a different way in Xcode 4.2 to start the main function:
int main(int argc, char *argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, nil,
NSStringFromClass([PlistAppDelegate class]));
}
}
and
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
Does anybody know the difference between those two?
The first one is using ARC, which is implemented in iOS5 and above to handle memory management for you.
On the second one, you're managing your own memory and creating an autorelease pool to handle every autorelease that happens inside your main function.
So after reading a bit on what's new on Obj-C with iOS5 it appears that the:
#autoreleasepool {
//some code
}
works the same as
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// some code
[pool release];
with the difference that the last one would throw an error on ARC.
EDIT:
The first one is using ARC or not.