Memory management mechanism
The current popular memory management mechanisms are mainlyGC
andRC
Two types.
-
GC
(Garbage Collection): Garbage collection mechanism, regularly searches for objects that are no longer used, and frees up the memory occupied by objects. -
RC
(Reference Counting): Reference Counting mechanism. Use reference counts to manage the memory of an object. When you need to hold an object, make its reference count +1; when you do not need to hold an object, make its reference count -1; when an object's reference count is 0, the object will be destroyed.
Objective-C
Supports three memory management mechanisms:ARC
、MRC
andGC
,butObjective-C
ofGC
The mechanism has platform limitations, onlyMacOS
Under development,iOS
The development usesRC
Mechanism fromMRC
Until nowARC
。
A newly created OC object reference count is 1 by default. When the reference count is reduced to 0, the OC object will be destroyed, freeing up the memory space it consumes.
Callretain
Will make the reference count of the OC object +1, callrelease
Will make the reference count of the OC object-1
Summary of experience in memory management
- When called
alloc
、new
、copy
、mutableCopy
The method returns an object, and when this object is not needed, it must be calledrelease
orautorelease
Let it be released - If you want to have an object, let its reference count +1; if you don't want to have an object, let its reference count -1
- You can use the following private functions to view the situation of automatically releasing the pool
extern void _objc_autoreleasePoolPrint(void);
As a result, we have made a preliminary understanding of the concept of "reference counting". The "object" in Objective-C manages its memory life cycle through the reference counting function. So, how are the reference counts of objects stored? In which data structure is it stored?
First of all, I have to mentionisa
。
isa
-
isa
Pointers are used to maintain the relationship between "object" and "class" and ensure that objects and classes can passisa
Pointer finds the corresponding methods, instance variables, attributes, protocols, etc.; - Before the arm64 architecture,
isa
It's just an ordinary pointer that points directly toobjc_class
, storedClass
、Meta-Class
The memory address of the object.instance
The object'sisa
Point toclass
Object,class
The object'sisa
Point tometa-class
object; - Starting with the arm64 architecture,
isa
Optimized, usingnonpointer
It means that it becomes a common body (union
) structure, and also uses bit fields to store more information. Separate 64-bit memory data to store a lot of things, 33 of which are used to storeclass
、meta-class
The memory address information of the object. To pass the bit operationisa
Value of& ISA_MASK
Only by getting the maskclass
、meta-class
The memory address of the object.
// struct objc_object { Class isa; // Before arm64 architecture}; // struct objc_object { private: isa_t isa; // Start with arm64 architecture}; union isa_t { isa_t() { } isa_t(uintptr_t value) : bits(value) { } Class cls; uintptr_t bits; #if SUPPORT_PACKED_ISA // extra_rc must be the MSB-most field (so it matches carry/overflow flags) // nonpointer must be the LSB (fixme or get rid of it) // shiftcls must occupy the same bits that a real class pointer would // bits + RC_ONE is equivalent to extra_rc + 1 // RC_HALF is the high bit of extra_rc (. half of its range) // future expansion: // uintptr_t fast_rr : 1; // no r/r overrides // uintptr_t lock : 2; // lock for atomic property, @synch // uintptr_t extraBytes : 1; // allocated with extra bytes # if __arm64__ // Under the __arm64__ architecture# define ISA_MASK 0x000000ffffffff8ULL // Used to retrieve the memory address of Class and Meta-Class objects# define ISA_MAGIC_MASK 0x000003f000000001ULL # define ISA_MAGIC_VALUE 0x000001a000000001ULL struct { uintptr_t nonpointer : 1; // 0: Represents an ordinary pointer, storing the memory addresses of Class and Meta-Class objects // 1: It means that it has been optimized and uses bit domain to store more information uintptr_t has_assoc : 1; // Is there any associated object set? If not, it will be faster when released uintptr_t has_cxx_dtor : 1; // Is there a C++ destructor (.cxx_destruct)? If not, it will be faster when released uintptr_t shiftcls : 33; //Storing memory address information of Class and Meta-Class objects uintptr_t magic : 6; // Used to determine whether the object has not completed initialization during debugging uintptr_t weakly_referenced : 1; // Is it a weak reference pointing to it? If not, it will be faster when it is released uintptr_t deallocating : 1; // Is the object being released uintptr_t has_sidetable_rc : 1; // If it is 1, it means that the reference count is too large and cannot be stored in isa. The exceeded reference count will be stored in a hash table called the SideTable structure uintptr_t extra_rc : 19; // The value stored in it is the number of reference counts outside the object itself, retainCount - 1# define RC_ONE (1ULL<<45) # define RC_HALF (1ULL<<18) }; ...... // Under the __x86_64__ architecture};
ifisa
Nononpointer
, i.e. before the arm64 architectureisa
pointer. Since it's just a normal pointer, it's storedClass
、Meta-Class
The memory address of the object, so it cannot store the reference count itself, so the reference count of the object was stored in aSideTable
StructuralRefCountMap
(Reference Count Table) hash table.
ifisa
yesnonpointer
, then it itself can store some reference counts. From aboveunion isa_t
We can know from the definition ofisa_t
There are two reference count related things stored in it:extra_rc
andhas_sidetable_rc
。
- extra_rc: The value stored in it is the number of reference counts outside the object itself. If these 19 bits are not enough to be stored,
has_sidetable_rc
The value of 1 will become 1; - has_sidetable_rc: If it is 1, it means that the reference count is too large and cannot be stored in
isa
In, then the exceeded reference count will be storedSideTable
ofRefCountMap
middle.
So, ifisa
yesnonpointer
, then the reference count of the object is stored in itsisa_t
ofextra_rc
Chinese andSideTable
ofRefCountMap
middle.
SideTable
// struct SideTable { spinlock_t slock; // Spin lock RefcountMap refcnts; // Reference count table (hash table) weak_table_t weak_table; // Weak reference table (hash list) ...... }
SideTable
Stored inSideTables()
middle,SideTables()
It is essentially a hash table. You can use the object pointer to get which one it corresponds to (reference count table or weak reference table) is in.SideTable
middle. In non-embedded systems,SideTables()
64 out ofSideTable
. The following isSideTables()
Definition:
// static objc::ExplicitInit<StripedMap<SideTable>> SideTablesMap; static StripedMap<SideTable>& SideTables() { return (); }
Therefore, looking for the reference count table of an object requires two hash searches:
- ① The first time is to search for the current object's memory address through hashing
SideTables()
Take out where it isSideTable
; - ② The second time, based on the memory address of the current object, search for the
SideTable
In-houserefcnts
Take out its reference count table.
Use multipleSideTable
+Separated lock technical solution is to ensure thread safety while taking into account access efficiency
The above is the detailed content of the iOS memory management reference counting example analysis. For more information about iOS memory management reference counting, please pay attention to my other related articles!