OC object’s memory and pointer
- We write every day
[[xxx alloc] init]
But never exploredalloc
andinit
What’s going on inside? With that in mind, let’s take a look at it through a simple piece of codeOC
Object initialization:
FFObj *obj = [FFObj alloc];
FFObj *o1 = [obj init];
FFObj *o2 = [obj init];
NSLog(@"%@ -- %p -- %p", obj, obj, &obj);
NSLog(@"%@ -- %p -- %p", o1, o1, &o1);
NSLog(@"%@ -- %p -- %p", o2, o2, &o2);
Copy the code
- Running the above code produces the following print:
<FFObj: 0x600003a28170> -- 0x600003a28170 -- 0x7ffee41dcc38
<FFObj: 0x600003a28170> -- 0x600003a28170 -- 0x7ffee41dcc30
<FFObj: 0x600003a28170> -- 0x600003a28170 -- 0x7ffee41dcc28
Copy the code
- Here is:
- Conclusion:
- By looking at the memory addresses of the three objects,
alloc
Method opens up memory whileinit
The method does nothing to memory, so these three objects are exactly the same. - The addresses of the three Pointers point to the heap space (0x6 begins with the heap), while the three Pointers themselves are in the stack (0x7 starts with the stack).
- By looking at the memory addresses of the three objects,
So, how does alloc open up memory space? Does init really do nothing? Let’s move on.
Looking for alloc
To find the alloc location and the underlying source call process, you can:
Breakpoint tracking
-
Start by adding a breakpoint to the alloc call location
-
Hold down the Control key and click Next to track view:
-
The key function objc_alloc is found
-
Assembly analysis
- At the breakpoint location, click on the Xcode navigation bar
Debug->Debug Workflow->Always Show Disassembly
To view the assembly code: - The key function is found
objc_alloc
- At the breakpoint location, click on the Xcode navigation bar
Breakpoints by given function symbols
, such as directlyalloc
Add to the symbol breakpoint, and then trace the view.- Get the key function
objc_alloc
After that, we add it to the symbolic breakpoint:
It turns out that objc_alloc is in libobjc.a. dylib, which is where the underlying source code for the Objc framework is, but fortunately Apple has opened up this code, so we can go down and explore it.
The source address
- Source Browser
- Apple OpenSource
Alloc source process analysis
- Found by breakpoint debugging or global search
alloc
methods -
_objc_rootAlloc
-
callAlloc
- the
callAlloc
After that, instead of simply wrapping the method calls layer by layer, there is a lot of logic, which means that this is where we start to analyze the source logic. - added
#if __OBJC2__
Indicates that the code within the code block belongs toobjc2.0
Version, which is the version we are currently using.fastpath
Is defined as#define fastpath(x) (__builtin_expect(bool(x), 1))
, which indicates the currentif
Judge, there is a higher probability oftrue
slowpath
Is defined as#define slowpath(x) (__builtin_expect(bool(x), 0))
, which indicates the currentif
Judge, there is a higher probability offalse
__builtin_expect
The usage, for__builtin_expect(bool(x), y)
Is a Boolean valuebool(x)
There is a higher probability ofy
, enables the compiler to logically optimize the code jump here during compilation, resulting in higher performance assembly code.
-
_objc_rootAllocWithZone
-
_class_createInstanceFromZone
- Looks like we’re finally here
alloc
The core part of the process, the method carries out the internal memory calculation and allocation logic instanceSize
Calculate the size of the memory space required- According to the
if (zone)
Judge to callmalloc_zone_calloc
orcalloc
Allocate memory - in
calloc
Before, assign toobj
Is a piece of dirty memory to executecalloc
After that,obj
To actually allocate memory,calloc
Pre – and post-executionobj
See the following figure for memory - At this time
po
Out of theobj
Is only a memory address without a type, indicating that theobj
There is no binding to the class - through
if (! zone && fast)
Judgment call separatelyobj->initInstanceIsa(cls, hasCxxDtor)
orobj->initIsa(cls)
To initialize theisa
That will beobj
Bound to the class - through
if (fastpath(! hasCxxCtor))
Judge, directly returnobj
Or returnsobject_cxxConstructFromClass(obj, cls, construct_flags)
- Looks like we’re finally here
-
instanceSize
- When you have a cache, you’re going to go to
fastInstanceSize
- When you don’t have a cache, you go to
alignedInstanceSize
- If I end up with
size < 16
Is returned16
- When you have a cache, you’re going to go to
-
alignedInstanceSize
word_align
Byte alignment
Parameters in the algorithmx
The value of the derived fromunalignedInstanceSize()
, i.e.,data()->ro()->instanceSize
, the size of the instance variable, byivars
Decision.WORD_MASK
The value of the64
A for7
, in 32-bit3
-
Byte Alignment algorithm description (
A 64 - bit
)(x + WORD_MASK) & ~WORD_MASK
x = 8
WORD_MASK = 7
(8 + 7) & ~7
=15 & ~ 7
0000 1111&~ 0000 0111
=0000 1111&11111000
- The results for
0000, 1000,
=8
- namely
(x + y) & ~y
Calculation isy + 1
Integer multiples of, is equal to(x + y) >>z <<z
, includingZ is logarithm base 2 of y
, i.e.,When y is equal to 8, z is equal to 3
- It follows that,
alignedInstanceSize()
The final result is8-byte alignment
, take8 multiples of
- So why
8-byte alignment
How about memory? Why does memory end up allocated ifThe < 16
to= 16
?- The maximum unit length is
8
, such asPointer to the
, other common data types can be8
Within the size is stored. - Constant to
8
After storing data in units,CPU
Or we can keep it constant8
To read data in units, there is no need to constantly change the access length, which is throughExchange space for time
The way to improveCPU
Access efficiency. - In order to
16
Make room for minimum because there will be at least one classisa
Members, andisa
isStructure pointer
The type and length are8
And open up more space for fault-tolerant handling.
- The maximum unit length is
-
fastInstanceSize
- call
align16
implementation16-byte alignment
- call
-
initInstanceIsa
initInstanceIsa
Will be calledinitIsa
-
initIsa
initIsa
toisa
To bindif (! nonpointer)
Determines whether pointer optimization is performed for the representation