OBJECTIVE-C Memory Management-Automatic release pool (autorelease)

Source: Internet
Author: User
transferred from: http://stephen830.iteye.com/blog/1461354 if the life cycle of an object is obvious, it is easy to know when the new object is to be used and when it is no longer needed, in which case the manual retain and release are used directly to determine its survival and death. But sometimes it's not that easy to know when an object is no longer in use. If the following code, it looks very simple:

Sample.h Class Interface Section

#import < foundation/foundation.h >
@interface sample:nsobject {

}

-(nsstring*) toString;

@end

SAMPLE.M Class Implementation Section

#import "Sample.h"

@implementation Sample


-(nsstring*) toString
{
	nsstring* str = [[NSString alloc] initwithformat:@ "This is%@ class" @ "Sample"];
	return str;
}
@end

Called in the main function

#import <Foundation/Foundation.h>
#import "Sample.h"

int main (int argc, const char * argv[]) {	
	
	Sample *s = [Sample new];
	NSLog (@ "%@", [s toString]);
	[s release];
	
    return 0;
	
    
}

I do not know if you realize that this code has a memory leak problem, because SAMPLE.M's ToString method generates an instance of the NSString class, but the main function finally releases only the instance S of sample, but does not release the string instance of the NSString class.

To correct this error, the main function should be changed to:

int main (int argc, const char * argv[]) {	
	
	Sample *s = [Sample new];
	nsstring* str = [s toString];
	NSLog (@ "%@", str);
	[STR release];//manual Release NSString string instance
	[s release];
	
    return 0;	
    
}

This hidden error can easily occur and is easily overlooked. For this obj-c reference to the Autorelease pool, each time you create a project with Xcode, you may have noticed a code template similar to the following:

int main (int argc, const char * argv[]) {	
	
	NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
	
	Insert Code
	here ... NSLog (@ "hello,world!");
	
	[Pool drain];	
    return 0;	
    
}

That is, Xcode writes a layer of NSAutoreleasePool to the developer's code. This pool is similar to a stack in a data structure (stack), which is equivalent to a container, and each time an object calls the Autorelease method (the formal argument in obj-c should be that the object sends a autorelease message), the object's reference count does not really change. Instead, add a record to the pool and note the object's requirements. Finally, when the pool sends a drain or release message, this requirement for all objects in the pools is executed (that is, all objects in the pool are notified before the pooling is destroyed, and all the release messages are actually reduced by the reference count. If the object has previously sent a autorelease message)

Let's take a look at the basic use, first add a property int flag to sample (to see which instance is being destroyed when destroying), and rewrite dealloc () to output some information when released

Sample.h

#import <Foundation/Foundation.h>

@interface sample:nsobject {	

}

-(nsstring*) toString;

Add a property of type int flag
@property int flag;

@end

Sample.m

#import "Sample.h"

@implementation Sample

//auto-Generate attribute flag setter and getter method
@synthesize flag;

-(nsstring*) toString
{
	nsstring* str = [[NSString alloc] initwithformat:@ "This is sample%d", flag];
	return str;
}


-(void) dealloc
{
	NSLog (@ "Sample%d is going to die.", flag);
	[Super Dealloc];
}
@end

Use the main function after automatically releasing the pool

#import <Foundation/Foundation.h>
#import "Sample.h"

int main (int argc, const char * argv[]) {	
	
	NSAutoreleasePool * Pool = [[NSAutoreleasePool alloc] init];
	
	Sample *S1 = [Sample new];
	Sample *S2 = [Sample new];
	
	s1.flag=1;
	s2.flag=2;
	
	[S1 autorelease];
	[S2 autorelease];
	
	
	[Pool drain];	
    return 0;	
    
}

The result of the operation is:

2011-02-24 13:28:09.759 memorymanage[282:a0f] Sample 2 is going to die.
2011-02-24 13:28:09.769 memorymanage[282:a0f] Sample 1 is going to die.

From the results, the pool is a last-in-first-out, i.e. the first release of the final autorelease (conforming to the characteristics of the stack data structure). Then go back to the problem of memory leaks in the ToString method mentioned earlier, after understanding the basic principle of pool, just replace the return str with retrun [str autorelease], that is, the string is registered in the pool, so when [pool drain], All enlisted objects are automatically called the release method and are freed.

The auto-release pool is functionally understood as a delay-release technique: by sending a autorelease message, registering with the auto-release pool, indicating that it will send release messages to destroy itself when the pool is destroyed.

Finally, some points to note:

1, nsautoreleasepool instance pool itself is also an object, also need to release, so the end also need [pool release] or [pool drain], it is this line of code, it will be all the objects in the pool are released simultaneously. ---Note: Drain is only available for Max OS High version, low version not applicable, and release generic, the other is not much different

2, pool in release, just simply let all the objects in the pool send release, there is no other mystery. (that is, the reference count for all objects in the pool is reduced by 1) so if you have previously forced retain of a reference count for an object, even if the pool is release, the objects in the pools are still likely to be destroyed because the reference count is still greater than 1. For example, the following code:

#import <Foundation/Foundation.h>
#import "Sample.h"

int main (int argc, const char * argv[]) {	
	
	NSAutoreleasePool * Pool = [[NSAutoreleasePool alloc] init];
	
	Sample *S1 = [Sample new];//retaincount=1
	Sample *S2 = [Sample New];//retaincount=1
	
	s1.flag=1;
	s2.flag=2;
	
	NSLog (@ "s1.retaincount=%d,s2.retaincount=%d", [S1 retaincount],[s2 Retaincount]);
	
	[S1 autorelease];//retaincount is still 1
	
	NSLog (@ "s1.retaincount=%d,s2.retaincount=%d", [S1 RETAINCOUNT],[S2 Retaincount]);
	
	[S2 retain];//retaincount=2
	[S2 autorelease];//retaincount is still 2	
	
	NSLog (@ "S1.retaincount=%d,s2.retaincount =%d ", [S1 retaincount],[s2 Retaincount]);	
	
	[Pool drain];	
   
	return 0;	
    
}

Operation Result:

2011-02-24 13:49:22.558 memorymanage[461:a0f] S1.retaincount=1,s2.retaincount=1
2011-02-24 13:49:22.566 memorymanage[461:a0f] S1.retaincount=1,s2.retaincount=1
2011-02-24 13:49:22.567 memorymanage[461:a0f] s1.retaincount=1,s2.retaincount=2
2011-02-24 13:49:22.578 memorymanage[461:a0f] Sample 1 is going to die.

Because S2 sends a retain message, it increases its reference count to 2, so eventually S2 is not destroyed even after the pool is released.

3, in Iphone/ipad and other memory limited handheld devices, do not recommend the use of autorelease, because in the final analysis this is a delay release, if your program has been running, the code has not been implemented to [pool release], even if there are many objects no longer needed, But the memory they occupy is not really released.

4, do not put a lot of cyclic operation between the same nsautoreleasepool, the same reason, so that the pool has a large number of objects, causing the program to occupy more memory at run time. For example, the following code:

int main (int argc, const char * argv[]) {	
	
	NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];	
		
	int i;
	
	For	(i=0;i<10000;i++) {
		Sample *s = [Sample new];
		S.flag = i;
		NSLog (@ "%@", [s toString]);
		[s autorelease];
	}
   
	[Pool release];
	return 0;	
    
}

When the above code runs, it must wait until the end of the loop before destroying the object. This can be improved for the following:

int main (int argc, const char * argv[]) {	
	
	NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];	
		
	int i;
	
	For	(i=0;i<10000;i++) {
		Sample *s = [Sample new];
		S.flag = i;
		NSLog (@ "%@", [s toString]);
		[s autorelease];
		if (i% 100==0)
		{
			[pool release];
			Pool = [[NSAutoreleasePool alloc] init];
		}
	}
   
	[Pool release];
	return 0;	
    
}

So that whenever there are 100 objects in the pool, it is released once, so that the program consumes much less memory when it runs.

The

Finally copied from the book a section of the Golden Law called Cocoa Memory Management: If I use the new, alloc, or copy method to get an object, I have to release (release) or automatically release (autorelease) the object

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.