iOS memory management

Source: Internet
Author: User

iOS memory management

Main references: "Effective OBJECTIVE-C 2.0", "Objective-c advanced programming iOS and OS X multithreading and memory Management"

In the study of memory management, consulted a lot of information, fragmented records in Youdao Cloud notes, summarized here, I hope in the convenience of their own view can help everyone.

1. Reference counting

Under the reference count schema, each object has a counter that can be incremented or decremented to indicate how many things are currently trying to keep this object alive. This is called the retention count (retain count) in OC, but it can also be called a reference count. If you want to keep an object alive, increment its reference count, and after it is exhausted, it decrements its reference count. The count becomes 0, which means no one is concerned about the object, so it can be destroyed.

MRC: In manual reference counting mode, the NSObject protocol declares the following three methods for manipulating counters, retain,release,autorelease.
-(Instancetype) retain objc_arc_unavailable;
-(OneWay void) release objc_arc_unavailable;
-(Instancetype) autorelease objc_arc_unavailable;

ARC: Apple's official note:
The arc mechanism is used in OC to allow the compiler to manage memory. Setting the arc to a valid state in the next-generation Apple LLVM compiler eliminates the need to type in the retain or release code again, which reduces the risk of program crashes, memory leaks, and so on, greatly reducing the effort on the part of the development program. The compiler is fully aware of the target object and can immediately release objects that are no longer in use. As a result, applications will be predictable and run smoothly with a significant increase in speed.

Although ARC is now recommended in the project, it is very useful to understand MRC.

2. Reference counting memory Management thinking mode

Let's ignore arc first to consider how to think about reference-counting memory management.

    1. Self-generated objects, held by themselves
    2. Non-self-generated objects, you can also hold
    3. Frees the object when it is no longer needed
    4. Objects not owned by themselves cannot be freed
2.1 The object of their own production, held by themselves

The method name that starts with the following name means that the object that you build is held by itself:

  • Alloc
  • New
  • Copy
  • Mutablecopy

In OC, the method name embodies memory management semantics, and the method name starting with the above 4 names means "the generated object is owned by itself" or "the generated object is owned by the caller". "The generated object holds itself" means that the code that calls the four methods above is responsible for releasing the object returned by the method.

{    //调用[[NSObject alloc]init]方法会在堆上产生一个对象,并且没有被release和autorelease。这个堆上的对象目前的引用计数为1    //把这个对象的指针赋值给obj。赋值不会导致引用计数的变化,相当于通过obj可以拿到这个堆上的对象使用了。    id obj = [[NSObject alloc]init];    //这个代码段快要结束了,把这个堆上的对象释放掉,不然会产生内存泄漏。    [obj release];  }
2.2 Not self-generated objects, you can also hold

Objects obtained using a method other than alloc/new/copy/mutablecopy, because they are not generated and held by themselves, are not the owner of the object.

//取得非自己生产并持有的对象//调用[NSMutableArray array]方法,会在堆上产生一个对象,这个对象被调用了autorelease方法,它会再下一次运行循环的时候被release。可以把这个对象想象成引用计数为0的对象(虽然是过一段时间才变为0),只有retain一下,才能持有这个对象。id obj = [NSMutableArray array];//取得的对象存在,但自己不持有对象//NSMutableArray对象被赋给变量obj,但变量obj自己并不持有该对象。使用retain方法可以持有对象。//取得非自己生产并持有的对象id obj = [NSMutableArray array];//取得的对象存在,但自己不持有对象[obj retain];//自己持有对象

By the Retain method, objects that are not generated by themselves are the same as those generated and held by the Alloc/new/copy/muablecopy method.

2.3 Release This object when you no longer need the object you hold

The holder is obligated to release the object once it is no longer needed. Release using the release method.

//自己生产并持有对象id obj = [[NSObject alloc]init];//自己持有对象[obj release];//释放对象,指向对象的指针仍然被保留在变量obj中,貌似能够访问,但对象一经释放绝对不可访问。

Thus, objects generated and held by themselves using the Alloc method are freed by the release method.
Objects produced and held using the Alloc/new/copy/mutablecopy method, or objects held with the Retain method, must be released using the release method once they are no longer needed.

If you want to use a method to generate an object and return it to the caller of the method, what about its source code?

- (id)allocObject{    //自己生成并持有对象    id obj = [[NSObject alloc]init];    //自己持有对象    return obj;}

As shown in the example above, returning the object generated and held with the Alloc method intact will allow the caller to hold the object as well, note that Allocobject is compliant with the naming convention.

The Allocobject name conforms to the preceding naming convention, so it is exactly the same as the object generated and held by the Alloc method, so using the Allocobject method means "build and hold the object yourself."

So, call the [Nsmutablearray array] method to make the object exist, but do not own the object, but also how to implement it? Depending on the naming convention, you cannot use a method name that begins with Alloc/new/copy/mutablecopy, so use object as the method name.

-(id)object{    id obj = [[NSObject alloc]init];    //自己持有对象    [obj autorelease];    //取得的对象存在,但自己不持有对象    return obj;}

In the example above we used the Autorelease method. Using this method, you can make the acquired object exist, but you do not hold the object yourself. Autorelease provides the ability to automatically and correctly release (call the Release method) when an object is out of the specified range of existence.
The autorelease is to automatically call the release method when the pool ends by registering the object with the auto-free pools.

Using the Array class method of the Nsmutablearray class, you can obtain objects that are not held by anyone, and these methods are implemented through Autorelease. In addition, it is important to note that the method names used to obtain objects that are not held by the naming convention cannot begin with alloc/new/copy/mutablecopy.

object];//取得的对象存在,但自己不持有//当然,也能通过retain方法将调用autorelease方法取得的对象变为自己持有。
object];//取得的对象存在,但自己不持有[obj1 retain];//通过retain使得自己持有对象
2.4 Non-self-held objects cannot be released

For objects generated and held with the Alloc/new/copy/mutablecopy method, or objects held with the Retain method, it is necessary to release the object when it is not needed because the holder is itself. And the object obtained from this is absolutely not free. If you release objects that are not owned by yourself in your application, it can cause crashes.

//自己生成并持有对象id obj = [[NSObject alloc]init];//自己持有对象[obj release];//对象已释放[obj release];//释放之后再次释放已非自己持有的对象,应用崩溃

Or when the "acquired object exists, but does not own the object" release

object];//取得的对象存在,但自己不持有对象[obj1 release];//释放了非自己持有的对象,这肯定会导致应用程序崩溃

Help understand:
Use and possession are two different things. You can use this object, but you are not the owner of it. For example, the owner of an object has autorelease it, you can use this object, but unless you do retain, you are not the owner of it.
Considering memory management issues from the standpoint of ownership, it is easy to explain why you need to send autorelease messages to the returned NSString object in the description method:
Because it only creates a NSString object, but does not want to own it. The NSString object is created just to return a result and "hand over" the NSString object. Hand over, others love to own, do not love to forget.

3. ARC

In fact, the essential part of "reference-counting type of storage Management" has not changed in arc. Just as the name "Auto reference count" indicates, Arc simply helps us to deal with the relevant parts of reference counting automatically. This conclusion can be supported by the ability to set arc to be valid or invalid on the compilation unit. For example, you can choose to use or not use arc for each file.

The memory management thinking method described above is still valid in arc, but it is somewhat different from the writing of the source code. What kind of change does it have? The first step is to understand the additional ownership claims in arc.

3.1 Ownership modifier

In order to process objects in OC programming, variable types can be defined as ID types or various object types.
The so-called object type is a pointer to an OC class such as nsobject, such as nsobject*. The ID type is used to hide the class name portion of the object type, which is equivalent to the commonly used "void*" in the C language.
When arc is valid, the ID type and object type are different from other types of C, and the ownership modifier must be attached to the type. There are 4 types of ownership modifiers.

    • __strong
    • __weak
    • __unsafe_unretained
    • __autoreleasing

3.1.1 __strong modifier

The __strong modifier is the default ownership modifier for the ID type and object type.

ID obj = [[NSObject alloc]init];
The obj variable is actually appended with __strong ownership. Equivalent:

id __strong obj = [[NSObject

Let's look at the following code snippet:

//ARCid __strong obj = [[NSObject alloc]init];}

This source code explicitly specifies the scope of the C language variable. When arc is invalid, the source code can be described as follows:

//ARC无效id obj = [[NSObject alloc]init]; [obj release];}

As shown in the source code, the variable obj with the __strong modifier, when it goes out of scope of its variable, releases its assigned object when the variable is discarded.
As shown in the name strong, the __strong modifier represents a "strong reference" to an object. A variable that holds a strong reference is discarded when it goes out of scope, and the referenced object is freed as the strong reference expires.

3.1.2 __weak modifier
There are times when a circular reference problem occurs:

{        Dog* dog1 = [[Dog alloc]init];//狗对象;dog1持有狗对象的强引用        Cat* cat1 = [[Cat alloc]init];//猫对象;cat1持有猫对象的强引用        [dog1 setObj:cat1];//狗对象里的成员变量obj_持有猫对象的强引用        [cat1 setObj:dog1];//猫对象里的成员变量obj_持有狗对象的强引用        //现在狗对象的持有者是dog1、猫对象的成员变量obj        //现在猫对象的持有者是cat1、狗对象的成员变量obj    }    //因为dog1,cat1超出作用域,强引用失效,所以自动释放狗对象和猫对象,引用计数从2变为1    //此时两个对象中的成员互相引用两个对象,发生内存泄露

As in this case, there is only one object, but a circular reference (self-reference) occurs when the object holds itself.

    id test = [[Test alloc]init];    setObject:test];

Use the __weak modifier to avoid circular references. A weak reference cannot hold an object and has no effect on the object's reference count. Or that sentence, can use but do not hold, the holder put it release, you can not use. The circular reference problem can be solved by changing the modifier of the previous member variable to __weak.
The __weak modifier also has another advantage. When holding a weak reference to an object, if the object is discarded, the weak reference is automatically invalidated and is assigned nil. By checking whether a variable with the __weak modifier is nil, you can determine whether the assigned object is obsolete.

3.1.3 __unsafe_unretained modifier
The variable with the _unsafe_unretained modifier is the same as the variable with the __weak modifier, because the object that it generates and holds cannot continue to be owned by itself, so the resulting object is immediately freed. Here, the __unsafe_unretained modifier and the __weak modifier are the same.

The __unsafe_unretained modified variable is somewhat different from __weak: It is not assigned nil when the object is discarded.

3.1.4 __autorelease modifier
Replace the Autorelease method with a variable with the __autoreleasing modifier.
As mentioned earlier, objects obtained by means other than alloc/new/copy/mutablecopy, because they are not generated and held by themselves, are not the owner of the object.
When we write our own methods that do not begin with these, the compiler will follow the rules to call the Autorelease method on the object to be returned.
There is a situation:
For example, a method in NSData:

- (BOOL)writeToFile:(NSString *)path options:(NSDataWritingOptions)writeOptionsMask error:(NSError **)errorPtr;

We need to declare one NSError *error; and then put &error the incoming method in.
Here (NSError **)errorPtr , in fact, is equivalent to

*  __autoreleasing *)errorPtr

This will add the *error to the auto-release pool. The reason for this is to conform to the memory management thinking, the object that is obtained as the return value of the Alloc/new/copy/mutablecopy method is generated and held by itself, and in other cases, it is obtained without its own generated object. Therefore, using a variable with the __autoreleasing modifier as an object takes arguments, exactly as the object obtained from the return value of other methods other than Alloc/new/copy/mutablecopy, is registered to Autoreleasepool, and acquire objects that are not generated and held by themselves.

iOS memory management

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.