Objective-C memory management-autorelease pool)

Source: Internet
Author: User

If the lifecycle of an object is obvious, it is easy to know when to use a new object and when it is no longer needed. In this case, you can use manual retain and release to determine whether a person is born or dead. However, sometimes it is not easy to know when an object is no longer used. If the followingCode, Looks very simple:

Sample. H class interface Section

 
# Import <Foundation/Foundation. h> @ interface sample: nsobject {}-(nsstring *) tostring; @ end

Sample. M class implementation

 
# Import "sample. H "@ implementation sample-(nsstring *) tostring {nsstring * STR = [[nsstring alloc] initwithformat: @" this is % @ Class ", @" sample "]; return STR;} @ end

Call in 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 wonder if you realize that this code hasMemory leakageProblem, because the tostring method of sample. m generates an nsstring class instance, but the main function only releases the sample instance S, but does not release the nsstring class string instance!

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

 
Int main (INT argc, const char * argv []) {sample * s = [sample new]; nsstring * STR = [s tostring]; nslog (@ "% @", str); [STR release]; // manually release an nsstring instance [S release]; return 0 ;}

Such hidden errors are easily overlooked. For this reason, obj-C references the autorelease pool. Every time you use xcode to create a project, you may have noticed a code template similar to the following:

 
Int main (INT argc, const char * argv []) {ngutoreleasepool * Pool = [[ngutoreleasepool alloc] init]; // insert code here... nslog (@ "Hello, world! "); [Pool drain]; return 0 ;}

That is, xcode provides an external layer for the code written by developers.NSAID utoreleasepool. This pool is similar to the stack in the data structure, which is equivalent to a container. Every time an object calls the autorelease method (the formal statement in obj-C should be: the object sends the autorelease message ), object reference count andNoTrueChangeInstead, add a record to the pool and write down the requirements of the object. Finally, when the pool sends a drain or release message, the requirements for all objects in the pool are executed one by one (that is, all objects in the pool are notified before the pool is destroyed, when you send all the release messages, the reference count is actually reduced. If the object has previously sent the autorelease message)

Next let's take a look at the basic usage. First, add a int-type flag to the sample (used to see which instance is being destroyed at the time of destruction) and rewrite dealloc () so that some information can be output during release

Sample. h

 
# Import <Foundation/Foundation. h> @ interface sample: nsobject {}-(nsstring *) tostring; // Add an int type property flag @ property int flag; @ end

Sample. m

# Import "sample. H "@ implementation sample // automatically generate the setter and getter methods of the Flag attribute @ 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 the pool is automatically released

 
# Import <Foundation/Foundation. h> # import "sample. H "int main (INT argc, const char * argv []) {ngutoreleasepool * Pool = [[ngutoreleasepool 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 running result is:

13:28:09. 759 memorymanage [282: a0f] sample2Is going to die.
13:28:09. 769 memorymanage [282: a0f] sample1Is going to die.

From the results, the pool is post-in-first-out, that is, the first release of the autorelease (in line with the characteristics of the stack data structure ). Back to the memory leakage problem in the tostring method mentioned above, after understanding the basic principle of the poolReturn StrChangeRetrun [STR autorelease]That is to say, register the string in the pool. In this way, when [pool drain] is used, all registered objects will automatically call the release method to release the string.

The automatic release pool function can be understood asDelayed releaseTechnology: by sending the autorelease message, you can register with the Auto Release pool, indicating that you will send the release message to destroy yourself in the future when the pool is destroyed.

Last few pointsNotes:

1,The instance pool of the NSAID utoreleasepool is also an object and needs to be released, so it also needs [pool release] or [pool drain], which is exactly the same line of code, all objects in the pool will be released at the same time. -- Note: drain is only applicable to the max OS high version. It is not applicable to the lower version, but is applicable to the release General version. There is no big difference between the other versions.

2,When the pool is release, it simply sends release to all objects in the pool, and there is no other xuanjicang. (That is, reduce the reference count of all objects in the pool by 1). Therefore, if you use the code to force retain the reference count of an object before, even if the pool is release, objects in the pool may still not 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 []) {ngutoreleasepool * Pool = [[ngutoreleasepool alloc] init]; sample * S1 = [sample new]; // retaincount = 1 sample * S2 = [sample new]; // retaincount = 1s1. flag = 1; s2.flag = 2; nslog (@ "s1.retaincount = % d, s2.retaincount = % d", [S1 retaincount], [S2 retaincount]); [auts1 retaincount]; // 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 ;}

Running result:

13:49:22. 558 memorymanage [461: a0f] s1.retaincount = 1, s2.retaincount = 1
13:49:22. 566 memorymanage [461: a0f] s1.retaincount = 1, s2.retaincount = 1
13:49:22. 567 memorymanage [461: a0f] s1.retaincount = 1, s2.retaincount = 2
13:49:22. 578 memorymanage [461: a0f] sample 1 is going to die.

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

3,On iPhone/iPad and other handheld devices with limited memoryNot recommendedUse autorelease, because in the end it is a delay release, if yourProgramThe Code has been running and has not been executed until [pool release]. Even if many objects are no longer needed, the memory they occupy is not actually released.

4,Do not place a large number of cyclic operations between the same NSAID utoreleasepool. The same principle is true. This will cause a large number of objects in the pool and cause the program to occupy a large amount of memory during runtime. For example, the following code:

Int main (INT argc, const char * argv []) {ngutoreleasepool * Pool = [[ngutoreleasepool 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 is running, the object must be destroyed only after the entire loop ends. It can be improved as follows:

 
Int main (INT argc, const char * argv []) {ngutoreleasepool * Pool = [[ngutoreleasepool 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 = [[NSAID utoreleasepool alloc] init] ;}} [pool release]; return 0 ;}

In this way, when there are 100 objects in the pool, it will be released once, so that the memory occupied by the program during runtime will be much less.

Finally, I copied a piece of gold law called Cocoa memory management from the book:If I use the new, alloc, or copy method to obtain an object, I must release (release) or automatically release (autorelease) this 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.