IOS Memory Management

Source: Internet
Author: User
Tags shallow copy

First, preface

For the majority of people from C + + or Java to learn object-c (hereinafter referred to as OC), the language of OC looks very strange, it is a bit cumbersome to use.

OC does not have a garbage collection mechanism like Java, which means that OC programming requires programmers to manually manage memory. That's why it's annoying, but Apple has been advocating developers to write optimized code within limited hardware resources, using the least CPU and taking up the least amount of memory.

Second, the basic principle

Object is created:

When OC creates an object, it does not return the object directly, but instead returns a pointer to the object, so out of the basic type, we are basically using pointers in OC.

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

at [ClassA Alloc], a message notification system was sent to allocate memory space to ClassA objects, and a pointer to an uninitialized object was returned.

The uninitialized ClassA object takes over to the INIT message, and Init returns a pointer to the initialized ClassA object and assigns it to the variable A.

When an object is created and used, the user needs to manually dispose of the object.

[A dealloc];

If both pointers A and B point to the same memory address in the heap

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

ClassA *b = A;

[A dealloc];

When the third line is executed, pointer b becomes a headless pointer. This is a common mistake in C + + and we need to avoid such errors because headless pointers are dangerous.

Reference count:

OC uses a reference count (retain count) in memory management to hold a number inside an object that represents the number of times it is referenced. Init, new, and copy will have retain count plus 1. When destroying an object, the system does not call the Dealloc method directly, but first calls release, letting retain count minus 1, and when retain count equals 0, the system calls the Dealloc method to destroy the object.

The retain count is not automatically incremented when the pointer is assigned, and to avoid the above error, we need to manually retain the value at the time of assignment, allowing retain count to increase by 1.

ClassA *a = [[ClassA alloc] init]; Retain count = 1

ClassA *b = A;

[B retain]; Retain count = 2

[A dealloc];

This way, when you execute to line fourth, the retain count of the object is reduced by 1, not destroyed, and pointer B is still valid.

Memory leaks:

As shown in the preceding example, when a ClassA object is generated, pointer A has access to the object. If you lose access to an object without reducing the retain count to 0, a memory leak will occur. In other words, the allocated memory cannot be reclaimed.

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

A = nil;

Three, Autorelease Pool

To make it easier for programmers to manage memory, Apple introduced an automatic release pool (autorelease) in OC. You can automatically dispose of objects in the event that you follow some rules. But even with such a tool, OC memory still needs the programmer's attention (this automatic release pool and Java garbage collection mechanism is not the same thing, or, riding can not catch up with the Java mechanism, may not even eat the dust).

ClassA *a = [[[[ClassA alloc] init] autorelease];

Retain count = 1, but no release required

The principle of autorelease Pool:

The full name of the Autorelease pool is called NSAutoreleasePool, which is a class in OC. Autorelease pool is not innate, you need to create it manually

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

In general, when you create a new iphone project, Xcode automatically creates a autorelease pool for you, which is written in the main function.

A mutable array is included in NSAutoreleasePool to store objects declared as Autorelease. When the NSAutoreleasePool itself is destroyed, it iterates through the array, with each member of the release array (note that this is just release and does not destroy the object directly). If the member's retain count is greater than 1, then the object is not destroyed, causing a memory leak.

The default NSAutoreleasePool has only one, you can create NSAutoreleasePool in your program, objects marked as Autorelease will match the nearest nsautoreleasepool. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

Create some objects

Do something ...

[Pool release];

You can also nest the use of nsautoreleasepool, just as you nest using for.

Even though NSAutoreleasePool does not seem to be as cumbersome as manual release, the method of managing memory using NSAutoreleasePool is not recommended. Because in a nsautoreleasepool, if a large number of objects are marked as Autorelease, the memory will soar when the program runs, and will not be released until the NSAutoreleasePool is destroyed. If there are enough objects in it, you may receive a low memory warning from the system during the run, or directly crash.

Autorelease Pool Extension:

If you are curious to remove the NSAutoreleasePool code from the main function and then declare the object as autorelease in your own code, you will notice that the system does not send you an error message or a warning. Using memory detection tools to detect memory, you may be surprised to find that your object is still being destroyed.

In fact, when a new run loop is created, the system automatically creates a NSAutoreleasePool, and the NSAutoreleasePool cannot be deleted.

Please do not use NSString when doing memory testing. OC makes special handling of strings

NSString *str =[[NSString alloc] stringwithstring:@ "123"];

When you output the retain count of STR, you will find that retain count is greater than 1.

Iv. Manual management of memory

Using Alloc, new, copy to create an object with retain count equal to 1, you need to release the object with release. Who creates, who goes to release. Objects created in methods other than this 3-hour method are declared by default by the system as autorelease.

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

ClassA *b = A;

[B retain];

Do smoething

[B release];

b = nil;

When assigning a pointer to another pointer, the number of references to the object pointed to by the A pointer does not increase, that is, the retain count of the object remains equal to 1. Only after retain, retain count will add 1. Then, if [a release] is executed at this time, only the A pointer discards access to the object, the object's retain count minus 1, and the object is not destroyed. The object is destroyed only if B also executes the release method. Therefore, who retain, who will release.

The pointer is still present after the object is destroyed. So after the release, it's best to empty the pointer to prevent the headless pointer from appearing. By the way, it is legal to release a null pointer, but nothing happens.

If you create and return an object in a function, you need to declare the object as Autorelease

(ClassA *) Function ()

{

ClassA *a = [[[[ClassA alloc] init] autorelease];

return A;

}

If you do not do this, it will cause a memory leak.

V. Attributes and memory management

One thing Apple has never emphasized is the retain in the attribute. In fact, with retain in the attribute, it may have been retain once in the crafting setter at the time of assignment, so release is also required here.

@property is actually getter and setter, @synthesize is the synthesis of these 2 methods. Why can I use "." After declaring a property? To call the member variables directly? That's because after declaring the property, the system synthesizes a set method and a Get method based on the attributes you give. Use the "." is not directly related to attributes, if you are not too troublesome to write a set and get method inside your program, you can also use "." To invoke the variable.

@property (), if you do not write anything inside, then the system will default to set your property to:

@property (Atomic, assign) .....

About Nonatomic:

This property does not have a corresponding atomic keyword, even if I write it like this, but atomic only when you do not declare this feature, the system defaults, you can not take the initiative to declare this feature.

If your program has only one main thread, or if you are sure that your program will not access the same variable when it is 2 or running on the go, you can declare it as nonatomic. Specifies the nonatomic attribute, which is not considered a thread-safety issue when the compiler synthesizes accessors. If you have multiple threads accessing this variable at the same time, you can declare the attribute as atomic (by omitting the keyword nonatomic). In this state, the editor adds a lock (@synchronized) to the accessor when it synthesizes the accessor, and only one thread can access the variable at the same time.

However, the use of locks is a cost, a property declared as atomic, when set and get this variable is more slowly than declared as nonatomic. So if you're not going to write multithreaded code, it's best to declare the attribute attribute of the variable as nonatomic.

About assign, retain, and copy:

Assign is the default property attribute of the system, and it is suitable for almost all variable types of OC. For variables of non-object type, assign is the only optional attribute. But if you declare a variable of an object type as assign under the reference count, you will receive a warning from the compiler at compile time. Because assign only creates a weak reference (that is, a shallow copy of what is usually said) for the object attribute under the reference count. It can be dangerous to use variables like this. When you release the previous object, the assigned object pointer becomes a headless pointer. Therefore, when declaring a property for a variable of an object type, use assign as little as possible (or not).

About the setter of the assign synthesis, it looks like this:

-(void) Setobja: (ClassA *) A

{

Obja = A;

}

Before delving into the retain, write the setter that declares the Retain attribute:

-(void) Setobja: (ClassA *) A

{

If (Obja! = a)

{

[Obja release];

Obja = A;

[Obja retain]; Retain count plus 1 for objects

}

}

Obviously, in the retain setter, the variable retain once, so even if you're in the program

Self.obja = A;

Only this sentence, Obja still need to release, in order to ensure that the object retain count is correct. But if your code

Obja = A;

Just write the sentence, then here is just a shallow copy, the object's retain count does not increase, so write, you do not need to release obja in the back.

The difference between the 2 sentences is that the first sentence uses the compiler-generated setter to set the value of the Obja, and the second sentence is just a simple pointer assignment.

The copy setter looks like this:

-(void) Setobja: (ClassA *) A

{

ClassA * temp = Obja;

Obja = [a copywithzone:nil];

[Temp release];

}

Replication must be implemented by Copywithzone: This method, because the secondary copy feature only applies to the type that owns the method, that is, this class must support replication. Copy is to release the original object, and then let the pointer point to a copy of the new object. So even if you release the original object in the setter, you still need to release the new object (Dungeon) in the back.

Vi. the end of the

iOS development now the only way to manage memory is by reference counting, whether you like it or not. In a memory-starved machine, when you write programs, you can only step in, as much as possible to make your program free of memory space, and ensure that the system will not give you a warning. Even if Apple adds another memory management method (garbage collection) to the Mac OS X Snow Leopard (v10.5) system, it is not available for iOS at this time.

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.