当前位置:网站首页>[effective Objective-C] - memory management
[effective Objective-C] - memory management
2022-07-06 05:03:00 【Xuanmo】
List of articles
- Understanding reference counting
- With ARC Simplified reference counting
- stay dealloc Method to release the reference and unlisten
- To write “ Exception security code ” Pay attention to memory management issues
- Avoiding ring reservation with weak references
- With “ Automatic release of pool blocks ” Reduce peak memory
- use “ Zombie object ” Debug memory management issues
- Do not use retainCount
Understanding reference counting
Reference blog :
【iOS Development 】—— Automatic reference counting preliminary learning
【iOS Development 】—— A simple understanding of reference counting
How reference counting works
Under the reference counting Architecture , The object has a Counter , Used to indicate how many things want this object to survive . stay Objective-C
called “ Retention count ”, It can also be called “ Reference count ”.
NSObject The protocol declares the following three methods to operate counters :
Retain Increment reservation count
release Decrement retention count
autorelease To be cleaned up later “ Auto release pool ” when , Decrement reserve count again
Be careful
: Sometimes the call ends release
After the method , To avoid inadvertently using invalid objects , want Clear the pointer , such as :
[number release];
number = nil;
In this way, we can ensure that there will be no... That may point to invalid objects “ Hang the pointer ”.
Memory management in attribute access method
call retain
Method can keep objects . If the attribute is “strong
” Relationship , Then the set attribute value will be retained . such as , There is a man named foo The property of is named _foo Implemented by the instance object of , Then the setting method of this attribute will be like this :
- (void)setFoo:(id)foo {
[foo retain];
[_foo release];
_foo = foo;
}
This method is to keep the new value , Release old value , Then update the instance variable , Make it point to the new value . Order of attention .
Auto release pool
call autorelease
The count will be decremented later , Usually the next time “ The event loop ” Time decreasing , Or earlier . This method should be used when returning objects , such as :
- (NSString*)stringValue {
NSString* str = [[NSString alloc] initWithFormat:@"I am this : %@", self];
return str;
Return at this point str Object whose reservation count is more than expected , Because of the call alloc
Will increase the retention count by one , And then there is no corresponding release operation . So try to reduce it 1. But it cannot be released in the method str
, Otherwise, the method will not return , The system recycles the object . Here we can use it autorelease
.
- (NSString*)stringValue {
NSString* str = [[NSString alloc] initWithFormat:@"I am this : %@", self];
return [str autorelease];
such stringValue
Method to NSString
When the object is returned to the caller , This object must survive . And back to str
The object will be automatically released later .
From this we can add :autorelease It can prolong the life of objects , So that it can still survive for a period of time after crossing the method call boundary .
Reserved ring
When using the reference counting mechanism , One problem we should always pay attention to is “ Reserved ring ”, That is, multiple objects that reference each other in a ring , This will cause memory leaks , Because the loop will cause the retention count of the object not to drop to 0.
In a garbage collection environment , This situation is usually regarded as “ Isolated island ”, here , The garbage collector will recycle all three objects . And in the Objective-C
In the reference counting schema , You can't enjoy this convenience . Usually used “ Weak reference ” To solve this problem , or From the outside, one object in the command loop no longer retains another object .
The main points of :
- The reference counting mechanism manages memory through counters that can be incremented or decremented . After the object is created , Its retention count is at least 1. If the retention count is positive , The object continues to live . When the reserve count drops to 0 when , The object is destroyed .
- In the life of an object , The remaining objects retain or release this object by reference . The hold and release operations increment and decrement the reservation count, respectively .
With ARC Simplified reference counting
1. because ARC Automatically retain、release、autorelease、dealloc
Wait for the operation , So in ARC It is illegal to call these methods directly under .
2. Can not rewrite retain、release、autorelease
, Because these methods will not be called directly ,ARC Will call its Equivalent underlying function .
Use ARC Method naming rules that must be followed when
- The object returned by the method name starting with the following words Owned by the caller :
- alloc
- new
- copy
- mutableCopy
Owned by the caller intend : The code that calls the method beginning with the above four words is responsible for releasing the object returned by the method , in other words , The retention count of these objects is positive , The code that calls these four methods needs to offset one of the reservation operations .
If the method name does not start with the above four words , It means that the returned object does not belong to the caller .
- In addition to automatically calling “ Retain ” and “ Release ” Outside method ,ARC You can also perform some optimizations that are difficult to complete by hand .
- stay ARC When compiling code in the environment , Must consider “ Backward compatibility ”, To be compatible with those who do not use ARC Code for , Actually ARC Because of the special function it calls , It will bring autorelease Method to call
objc_autoreleaseReturnValue
function , holdretain
Methods toobjc_retainAutoreleaseReturnValue
. Here is a piece of code to cover upARC
How to optimize the program through special functions :
In order to get the best efficiency , The implementation code of these special functions varies from processor to processor . The following pseudocode describes the steps :
Leave memory management to the compiler and runtime components , Can make the code get a variety of optimization .
Memory management semantics of variables
ARC It also handles memory management of local variables and instance variables . By default , Each variable is a strong reference to the object .
- ARC Will use a safe method to achieve setter Method : Keep the new value first , Releasing old values , Finally, set the instance variable . It was used ARC after , There is no need to consider “ Boundary situation ”.
- In the application , The following modifiers can be used to change the semantics of local variables and instance variables :
_ _strong
: Default statement , Keep this value ._ _unsafe_unretained
: Do not keep this value , It may not be safe to do so , Because when you use variables again , Its object may have been recycled ._ _weak
: Do not keep this value , But variables can be used safely , Because if the system recycles this object , Then the variable will also be cleared ._ _autoreleasing
: Target object “ Pass by reference ” When giving methods , Use this special modifier . This value is automatically released when the method returns .
We often add modifiers to local variables , So break by “ block ” Introduced “ Reserved ring ”. The block automatically retains all the objects it captures , And if one of these objects retains the block itself , This may lead to “ Reserved ring ”, have access to _ _weak Local variables to break this retention ring . for example :
ARC How to clean up instance variables
ARC
You can manage the memory of instance variables , To manage memory ,ARC Will be in “ Reclaim memory allocated to objects ” Generate necessary Clean up the code . Variables with strong references , Must be released ,ARC Will be in dealloc
Method .ARC
Can borrow Objective-C++
To generate Clean up routines . Recycling Objective-C++
Object time , The object to be recycled calls all C++
Object's destructor . If the compiler finds that an object contains C++
object , It's called .cxx_destruct
Methods . and ARC
With this feature , The code needed to clean memory is generated in this method . If there is a non Objective- C
object ,ARC The superclass will be called in the generated memory cleanup code dealloc
Method .
ARC The code executed by the recycled object when the recycled object is automatically generated , So there is usually no need to write dealloc
Method .
Overwrite memory management method
Don't use ARC when , Memory management methods can be overridden . But use ARC Environmental time , Do not overwrite , To avoid disturbing ARC Analyzing the life cycle of objects .
The main points of :
- Yes ARC after , Programmers don't have to worry about memory management . Use ARC Programming , Many of the classes can be omitted “ Sample code ”.
- ARC The method of managing the life cycle of objects is basically : Insert in place “ Retain ” And “ Release ” operation . stay ARC In the environment , The memory management semantics of variables can be indicated by modifiers , The original needs to be executed manually “ Retain ” And “ Release ” operation .
- The object returned by the method , Its memory management semantics are always represented by method names .ARC Identify this as a rule that developers must follow .
- ARC Only responsible for managing
Objective-C
Object's memory . Pay special attention to :CoreFoundation
The object does not return ARC management , Developers must callCFRetain/CFRelease
.
stay dealloc Method to release the reference and unlisten
belong dealloc What to do in the method ? The main thing is to release the references owned by the object , Secondly, put the original configuration Observation behavior Clean it up . such as CoreFoundation
Objects must be released manually , use NSNotificationCenter
Subscribed to some kind of notification for the object , Then log out , Otherwise, sending notification to the recycled object will cause the program to crash . therefore dealloc The method can be written in this way :
- (void)dealloc {
CFRelease(coreFoundationObject);
[[NSNotificationCenter defaultCenter] removeObserve:self];
Be careful
: If you manage reference counts manually without ARC Words , Then finally, you need to call “[super dealloc]
”.ARC This will be done automatically , Therefore, manual management is generally not selected , Because manual management requires all you have Objective-C Objects are released one by one .
The main points of :
- stay dealloc In the method , What you should do is release references to other objects , And cancel the original subscription “ Key value observation ”(KVO) or
NSNotificationCenter
Wait for notice , Don't do anything else . - If the object holds system resources such as file descriptors , Then a method should be written specifically to release such resources . Such a class should be contracted with its users : Must be called after the resource is used up close Method .
- Methods that perform asynchronous tasks should not be in
dealloc
Call inside ; Methods that can only be executed in a normal state should not bedealloc
Call inside , This is because the object is already in the state of being recycled .
To write “ Exception security code ” Pay attention to memory management issues
Objective-C The error model of shows , Exceptions should only be thrown after serious errors occur , However, sometimes you still need to write code to catch and handle exceptions .
Let me introduce you @try、@catch、@finally:
@try {
... Logical processing
... Executed code , There may be exceptions . Once an exception is found , Then jump to catch perform . Otherwise, it will not execute catch What's in it
}
@catch {
... Exception capture
... Unless try There is an exception in the execution code , Otherwise, the code here will not execute
}
@finally{
... Logical execution results
... It will be carried out in any case , Include try catch It's used inside. return , It can be understood that as long as the implementation of try perhaps catch, I'll do it finally
}
stay @try
If an object is reserved in the block first , Then an exception is thrown before releasing it , Unless @catch
Block can handle this problem , Otherwise, the memory occupied by the object will leak .
For example, the following code :
If doSomethingThatMayThrow
Throw an exception , Because of the exception, the execution process will be terminated and jump to catch block , Cause what follows [object release]
The code will not execute , This will lead to memory leakage . The solution is use @finally block , Whether or not an exception is thrown , Will execute the code , So change the above code to the following :
If you want to manage reference counts manually , And you must catch exceptions , Then try to ensure that the code can clean up the objects correctly . If you use ARC And must catch exceptions , You need to open the compiler -fobjc-arc-exceptions
sign .
The main points of :
- When catching exceptions , Be sure to will try Clean up the objects created in the block .
- By default ,ARC Does not generate cleanup code required to safely handle exceptions . After the compiler flag is turned on , This code can be generated , However, it can lead to larger applications , And it will reduce operational efficiency .
Avoiding ring reservation with weak references
In the object graph , There is often a situation , That is, several objects refer to each other in some way , Thus forming “ Ring ”, In this case, it will cause Memory leak . The best way to avoid retaining rings is weak references . This kind of reference usually means “ Non ownership ”. Declare the property as unsafe_unretained
that will do . But it will be because of unsafe_unretained
The word "attribute value" indicates that the attribute value may be unsafe , And it is not owned by this instance , After the object referred to by the modified attribute is recycled , Calling methods on it again will crash the application . however OC There is another item related to ARC Accompanying runtime characteristics , Developers can safely use weak references : This is it. weak
Attributes, traits . It is associated with unsafe_unretained
It works exactly the same . However, as long as the system recycles attributes , The attribute value will be set to nil
.
The main points of :
- Set some references to weak, To avoid “ Reserved ring ”.
- weak References can be cleared automatically , It can also not be cleared automatically . Automatic emptying is with ARC And the introduction of new features . It is realized by the system in operation period . On weak references with auto clear function , The data can be read at will , Because this reference does not point to objects that have been recycled .
With “ Automatic release of pool blocks ” Reduce peak memory
There is a feature called “ Auto release pool ”, There are two ways to release objects : One is to call release
Method , Make its retention count decrease immediately ; The other is called autorelease Method , Add it to automatic “ Release pool ” in . The automatic release pool is used to store objects that need to be released at a later time . Empty the release pool , The system will send release
news .
Syntax used to create an automatic release pool :
@autoreleasepool {
//...
}
- Automatic release pool can nesting , When the system automatically releases objects , Will put it in the innermost pool . The advantage of such nested use is : This can be used to control the memory peak of the application , Make it not too high .
- Add an automatic release pool inside the loop , Wrap the code in the loop “ Automatic release of pool blocks ” in , Then the objects automatically released in the loop will be placed in this pool , Not in the main pool of threads .
- Peak memory It refers to the maximum memory usage of the application in a specific period .
- Automatic release pool mechanism It's like “ Stack ” equally . After the system has created the automatic release pool , Just push it into the stack , And empty the automatic release pool , It is equivalent to popping it from the stack . Perform an automatic release operation on the object , It is equivalent to putting it into the pool at the top of the stack .
The main points of :
- The auto release pool is arranged in the stack , Object received autorelease After the news , The system puts it in the top pool .
- Rational use of automatic release tank , Can reduce the memory peak of the application .
- @autoreleasepool This new method can create a more lightweight automatic release pool .
use “ Zombie object ” Debug memory management issues
Cocoa Provides “ Zombie object ” This convenient function , During the run time, the system will convert all the recycled instances into special “ Zombie object ”, Instead of actually recycling them . After the zombie object receives the message , It throws an exception , Therefore, zombie objects are the best way to debug memory management problems .
- take NSZombieEnabled Set the environment variable to YES, Turn on this function immediately .
- stay Xcode You can also turn on this option in : Edit... In the application Scheme, Select... On the left side of the dialog box “Run”, Then switch to “Diagnostics” Pagination , Finally check “Enable Zombie Objects” Options .
The main points of
- When the system recycles objects , You can't actually recycle it , It turns it into a zombie object . Through environment variables NSZombieEnabled This function can be turned on .
- The system will modify the object isa The pointer , Point it to a particular zombie class , This makes the object a zombie object . The zombie class can respond to all the selectors , The response mode is : Print a message containing the message content and its recipient , Then terminate the application .
Do not use retainCount
NSObject The following methods are defined in the Protocol , Used to query the reservation count before the object :
- (NSUInteger)retainCount
However ARC This method has been abandoned . So don't use it anymore retainCount Just fine .
The main points of :
- Object's retention count may seem useful , But it is not , Because at any given point in time “ Absolute reserve count ” Can not reflect the life span of the object .
- introduce ARC after ,retainCount The method was officially abolished , stay ARC Calling this method will cause the compiler to report an error .
边栏推荐
- Request (request object) and response (response object)
- 关于Unity Inspector上的一些常用技巧,一般用于编辑器扩展或者其他
- Summary of three log knowledge points of MySQL
- Class inheritance in yyds dry inventory C
- Pagoda configuration mongodb
- RT thread analysis - object container implementation and function
- Chip debugging of es8316 of imx8mp
- L'introduction en bourse de MSK Electronics a pris fin: 800 millions de RMB d'actifs de Henan étaient des actionnaires
- IPv6 comprehensive experiment
- Supreme Court, judgment standard of divorce cases
猜你喜欢
RT thread analysis - object container implementation and function
二叉树基本知识和例题
ISP learning (2)
Bill Gates posted his 18-year-old resume and expected an annual salary of $12000 48 years ago
acwing周赛58
Lepton 无损压缩原理及性能分析
Postman pre script - global variables and environment variables
GAMES202-WebGL中shader的編譯和連接(了解向)
RT thread analysis log system RT_ Kprintf analysis
F12 solve the problem that web pages cannot be copied
随机推荐
ISP学习(2)
Yolov5 tensorrt acceleration
Building intelligent gray-scale data system from 0 to 1: Taking vivo game center as an example
2021robocom robot developer competition (Preliminary)
ISP learning (2)
CUDA11.1在线安装
[classic example] binary tree recursive structure classic topic collection @ binary tree
Postman test report
驱动开发——第一个HelloDDK
驱动开发——HelloWDM驱动
Fuzzy -- basic application method of AFL
Simple understanding of interpreters and compilers
Application of Flody
What should the project manager do if there is something wrong with team collaboration?
Request (request object) and response (response object)
Acwing week 58
Leetcode dynamic planning day 16
Cve-2019-11043 (PHP Remote Code Execution Vulnerability)
Compilation et connexion de shader dans games202 - webgl (comprendre la direction)
[FreeRTOS interrupt experiment]