Memory Management Extensions (16.5.10)

Source: Internet
Author: User

Iphone/mac objective-c Memory Management tutorial and principle analysis

Objective

Beginners Objectice-c friends have a confused, always feel the objective-c memory management mechanism elusive, programs often memory leaks or inexplicably crashes. Here I summarize my own objective-c memory management mechanism of the research results and experience, wrote such a more sophisticated tutorial. I hope we can help you, and we welcome you to discuss it together.

The memory management involved in this article is for class that inherits from NSObject. A basic principle of OBJECTIVE-C's memory management mechanism with the. Net/java kind of fully automatic

Garbage collection mechanism is different, it is essentially a C language manual management, but slightly added some automatic methods.

1 Objective-c objects are generated on top of the heap, and after they are generated, a pointer is needed to point to it.

ClassA *obj1 = [[ClassA alloc] init];

2 Objective-c objects are not automatically destroyed after they are used, and need to execute dealloc to free up space (destroy) or memory leaks.

[Obj1 Dealloc]; this brings up a problem. The following code obj2 whether to call the

Dealloc?
ClassA *obj1 = [[ClassA alloc] init]; ClassA *obj2 = obj1;
[Obj1 Hello]; Output Hello
[Obj1 Dealloc];
[Obj2 Hello]; Can I execute this line and the next line? [Obj2 Dealloc];

No, because Obj1 and obj2 are just pointers, they point to the same object, [Obj1 Dealloc] has destroyed the object, and can no longer invoke [obj2 hello] and [Obj2 Dealloc]. Obj2 is actually an invalid pointer.

How do I avoid invalid pointers? Take a look at the next article.

3 Objective-c uses a reference count (ref count or Retaincount). Holds a number inside the object that represents the number of times the reference was referenced. For example, an object is pointed (referenced) by two pointers, then its retain count is 2. When the object needs to be destroyed, instead of calling Dealloc directly, release is called. Release will let retain count minus 1, only retain count equals 0, and the system will call Dealloc to actually destroy the object.

ClassA *obj1 = [[ClassA alloc] init]; When object is generated, retain count = 1

[Obj1 release]; Release makes retain count minus 1,retain count = 0,dealloc is called automatically and the object is destroyed

Let's look back at the problem of the invalid pointer, and change the dealloc to release to solve it?

ClassA *obj1 = [[ClassA alloc] init]; Retaincount = 1

ClassA *obj2 = obj1; Retain count = 1
[Obj1 Hello]; Output Hello
[Obj1 release]; Retain count = 0, the object is destroyed [obj2 hello];
[Obj2 release];
After [obj1 release], OBJ2 is still an invalid pointer. The problem depends

Not resolved. The workaround is shown in the next article.

4 objective-c pointer assignment, retain count does not increase automatically and requires manual retain.

ClassA *obj1 = [[ClassA alloc] init]; Retaincount = 1

ClassA *obj2 = obj1; Retain count = 1[obj2 retain]; Retain count = 2
[Obj1 Hello]; Output Hello
[Obj1 release]; Retain count = 2–1 = 1

[Obj2 Hello]; Output Hello
[Obj2 release]; Retain count = 0, object is destroyed problem solved! Note that if you do not call [Obj2 release], this

The retain count of the object is always 1, is not destroyed, and the memory leaks. (1-4 can refer to the example program in the attachment MEMMAN-NO-POOL.M)

This does not really memory leaks, but it seems a bit troublesome, there is no simple method? See the next article.

The Autorelease pool is introduced in 5 objective-c, which automatically frees objects in the event of some rules being adhered to. (Autorelease pool is still not. Net/java's automatic garbage collection mechanism)

5.1 Newly generated objects, as long as the call to Autorelease is OK, no need to call release!

ClassA *obj1 = [[[ClassA alloc] init]autorelease]; Retain count = 1 without calling release

5.2 The code is similar to the previous case where the pointer assignment is present.

ClassA *obj1 = [[[ClassA alloc] init]autorelease]; Retain count = 1

ClassA *obj2 = obj1; Retain count = 1
[Obj2 retain]; Retain count = 2
[Obj1 Hello]; Output hello//for Obj1, no calls (not actually called) Release[obj2 Hello]; Output Hello

[Obj2 release]; Retain count = 2-1 = 1

The attentive reader will surely find that the object has not been destroyed and when destroyed. Who's going to destroy it? (You can refer to the example program in the attachment MEMMAN-WITH-POOL.M), take a look at the next article.

6 Autorelease Pool principle analysis. (In fact, very simple, certain

Keep watching, or you will not understand the OBJECTIVE-C memory management mechanism. )

6.1 Autorelease Pool is not born and needs to be created manually. Only when you create an iphone project, Xcode will automatically write it for you. Autorelease Pool's real name is NSAutoreleasePool.

NSAutoreleasePool *pool = [[Nsautoreleasepoolalloc] init];

The 6.2 NSAutoreleasePool contains an array (Nsmutablearray) to hold all objects declared as Autorelease. If an object is declared as Autorelease, the system does its job of adding the object to the array.

ClassA *obj1 = [[[ClassA alloc] init]autorelease]; Retain count = 1, add this object to the Autorelease pool

6.3 NSAutoreleasePool itself at the time of destruction, it iterates through the array, and each member of the release array. If the retain count of the members in the array is 1, then Retaincount is 0 after release, and the object is formally destroyed. If the retain count of the members in the array is greater than 1, then the retain count is greater than 0 after release, and the object is still not destroyed and memory leaks.

6.4 The default is only one autorelease pool, usually similar to the following example.

int main (int argc, const char *argv[]) {
     NSAutoreleasePool *pool;     Pool = [[NSAutoreleasePool alloc] init];
     Do something
     [Pool release];
     return (0); }//Main

All objects marked as Autorelease are only destroyed by this pool

Before being destroyed. If you have a large number of objects marked as autorelease, this is obviously not a good use of memory, in the iphone this memory-constrained program is very easy to cause memory shortage. For example:

int main (int argc, const char *argv[]) {
     NSAutoreleasePool *pool = [[Nsautoreleasepoolalloc] init];
     int I, J;     for (i = 0; i <; i++)     {
          for (j = 0; J < 100000; J + +)

[nsstringstringwithformat:@ "1234567890"];//produces objects that are autorelease.

     }     [Pool release];     return (0);

}//Main

(You can refer to the sample program in the attachment MEMMAN-MANY-OBJS-ONE-POOL.M, the runtime through the monitoring tool can be found that the use of memory in a sharp increase, until the pool was destroyed before it was released) you need to consider the next article.

7 OBJECTIVE-C programs can be nested to create multiple autoreleasepool. When you need to create a large number of local variables, you can create an inline autorelease pool to release memory in a timely manner. (Thanks to netizens Hhyytt and Neogui's reminders, in some cases, the system will automatically create Autorelease pool, see chapter fourth)

int main (int argc, const char *argv[]) {
     NSAutoreleasePool *pool = [[Nsautoreleasepoolalloc] init];
     int I, J;     for (i = 0; i <; i++)
     {         NSAutoreleasePool *looppool =
[[NSAutoreleasePool alloc] init];         for (j = 0; J < 100000; J + +)

[nsstringstringwithformat:@ "1234567890"];//produces objects that are autorelease.

         [Looppool release];     }
     [Pool release];
     return (0); }//Main

Two formulas and the paradigm
1 formulas.
1.1 Who created, who released (similar to "who pollutes, who governs").

If you create an object from Alloc, new, or copy, you must call release or Autorelease. In other words, you don't create it, you don't have to release it.

For example, if you alloc an object in a function and this object is used only in this function, you must call release or autorelease in this function. If you alloc a member object in a class method, and you do not call autorelease, you need to call release in the Dealloc method of the class, and if Autorelease is called, Then nothing needs to be done in the Dealloc method.

1.2 Objects created by methods other than Alloc, new, or copy are declared autorelease.

1.3 who retain, who release. As soon as you call the retain, no matter how the object is generated, you call release. Sometimes your code is clearly not retain, but the system will add retain to the default implementation. Do not know why Apple's documentation does not emphasize this very important point, please refer to Paradigms 2.7 and III.

2 paradigm.

Paradigm is the template, that is, according to gourd painting scoop. Since different people have different understandings and habits, the paradigm I summarize is not necessarily suitable for everyone, but I can guarantee that doing so does not go wrong.

2.1 Create an object.
ClassA *obj1 = [[ClassA alloc] init];2.2 creates a Autorelease object. ClassA *obj1 = [[[[ClassA alloc] init]

Autorelease];
2.3 Release an object, empty the pointer immediately. (By the way.

One, release a null pointer is legal, but nothing happens)

[Obj1 release];
Obj1 = nil;
The 2.4 pointer is assigned to another pointer.
ClassA *obj2 = obj1;
[Obj2 retain];
Do something
[Obj2 release];
Obj2 = nil;
2.5 to create and return objects in a function, you need to set this object

Reset to Autoreleaseclassa *func1 () {

     ClassA *obj = [[[Classaalloc]init]autorelease];

return obj;}

2.6 The Dealloc method of the base class is called in the Dealloc method of the subclass-(void) dealloc
{

...

     [Super Dealloc]; }

2.7 Create and use property in a class.
2.7.1 declares a member variable.
ClassB *OBJB;
2.7.2 declares the property, plus the retain parameter.
@property (retain) classb* OBJB;
2.7.3 defines the property. (The default implementation of the property, see the third

Chapter
@synthesize OBJB;
2.7.4 In addition to the Dealloc method, always use the. Operator mode to

Call property.
SELF.OBJB or OBJA.OBJB
2.7.5 release This member variable in the Dealloc method. [OBJB release]; The sample code is as follows (please refer to the memman-in the attachment for detailed code)

PROPERTY.M, you need to pay special attention to when the object was destroyed. ):

@interface Classa:nsobject {
       classb* OBJB; }
@property (retain) classb* OBJB; @end
@implementation ClassA @synthesize OBJB; -(void) Dealloc {
     [OBJB release];
     [Super Dealloc]; }

@end
When 2.7.6 assigns a value to this property, there are manual release and

Autorelease two different ways. void Funcnoautorelease () {

     ClassB *OBJB1 = [[ClassB alloc]init];     ClassA *obja = [[ClassA alloc]init];     OBJA.OBJB = objB1;     [ObjB1 release];
     [Obja release]; }
void Funcautorelease () {
     ClassB *OBJB1 = [[[ClassB alloc]init]autorelease];
     ClassA *obja = [[[ClassA alloc]init]autorelease];
     OBJA.OBJB = objB1; }

Default implementations for three-@property (retain) and @synthesize

Explain here @property (retain) classb* objb, and @synthesize objb; what's going on behind it (the default implementation of Retainproperty). property is actually getter and setter, for the property with retain parameters, the following implementation (please refer to the attachment of MEMMAN-GETTER-SETTER.M, you will find that The result is the same as MEMMAN-PROPERTY.M):

@interface Classa:nsobject {
     ClassB *OBJB; }
-(ClassB *) GETOBJB; -(void) SETOBJB: (ClassB *) value; @end
@implementation ClassA-(classb*) GETOBJB {
     return OBJB; }
-(void) SETOBJB: (classb*) value {
       if (OBJB! = value)       {
           [OBJB release];
           OBJB = [value retain];       }

}

In SETOBJB, if the newly set value differs from the original value, you must release the original value object once, so that retain count is guaranteed to be correct.

Since we retain in class internally (albeit by default), we are going to release this member variable in the Dealloc method.

-(void) Dealloc {
     [OBJB release];
     [Super Dealloc]; }

Additional Information

When studying retain count, I don't recommend using NSString. Because in the following statement,

NSString *str1 = @ "constant string"; str1 's retain count is a very large number. Objective-c on regular

The volume string has been specially processed. Of course, if you create nsstring like this, get the retain count

Remains at 1
NSString *STR2 = [NSString

stringwithformat:@ "123"];

Memory Management Extensions (16.5.10)

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.