Having written OC code for years, alloc&init is an old friend. We use it all the time when we create objects, but we don’t really know what’s going on behind the scenes. This blog gives you an inside look at Alloc&Init.

1. Memory address after object alloc and init

As you can see, alloc creates a memory control. Init does not create a memory space and does not change the address of the memory space. P1, P2, p3 are sequential addresses that refer to the same memory space.

2. Alloc method execution flow

Note: The CPU instruction set of the real machine is different from that of the simulator

1. Set a breakpoint and run the program

2. Run the program to the breakpoint and add the symbolic breakpoint

Note that you are adding a symbolic breakpoint when you execute this breakpoint, which is to add a breakpoint to all of the class’s alloc methods.

3. Click Step over

4. Click to enter libobjc.a.dylib

You can see that the parent (NSObject) method +[NSObject alloc] is called, and you can see that the parent method JMP goes to _objc_rootAlloc

5. Continue adding symbolic breakpoints and trace _objc_rootAlloc

6. Click Step over to view _objc_rootAlloc

You can see that _objc_rootAlloc is called to _objc_rootAllocWithZone, so let’s go ahead and add a symbolic breakpoint

7. To continue adding symbolic breakpoints, look at _objc_rootAllocWithZone

Run a breakpoint to “_objc_rootAllocWithZone” and you can see retq in 22 return there, go back to _objc_rootAlloc and execute objc_msgSend

Alloc->_objc_rootAlloc ->_objc_rootAllocWithZone->objc_msgSend

3. How is alloc implemented in source code

Apple source code download address:

Apple Open Source

Source Browser

Objc4-818.2 is used here, and the specific source code configuration is not explained here.

1. Enter the alloc method and you can see that the first call is the one we saw above in libobjc.a.dylib

_objc_rootAlloc method

CallAlloc = _objc_rootAllocWithZone = _objc_rootAlloc = _objc_rootAllocWithZone = _objc_rootAllocCallAlloc is clearly not a JMP call to assembly but is optimized directly into assembly code), next look at the logic! cls->ISA()->hasCustomAWZ()

3.! CLS ->ISA()->hasCustomAWZ() ->hasCustomAWZ() -> CLS ->ISA()->hasCustomAWZ() Then _objc_rootAlloc->callAlloc again, _objc_rootAllocWithZone is called when there is a cache in the cache

4. Go to _objc_rootAllocWithZone and call _class_createInstanceFromZone

Alloc = _class_createInstanceFromZone; alloc = _class_createInstanceFromZone

_class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone, int construct_flags = OBJECT_CONSTRUCT_NONE, bool cxxConstruct = true, size_t *outAllocatedSize = nil) { ASSERT(cls->isRealized()); // Read class's info bits all at once for performance bool hasCxxCtor = cxxConstruct && cls->hasCxxCtor(); bool hasCxxDtor = cls->hasCxxDtor(); bool fast = cls->canAllocNonpointer(); size_t size; size = cls->instanceSize(extraBytes); if (outAllocatedSize) *outAllocatedSize = size; id obj; if (zone) { obj = (id)malloc_zone_calloc((malloc_zone_t *)zone, 1, size); } else { obj = (id)calloc(1, size); } if (slowpath(! obj)) { if (construct_flags & OBJECT_CONSTRUCT_CALL_BADALLOC) { return _objc_callBadAllocHandler(cls); } return nil; } if (! zone && fast) { obj->initInstanceIsa(cls, hasCxxDtor); } else { // Use raw pointer isa on the assumption that they might be // doing something weird with the zone or RR. obj->initIsa(cls); } if (fastpath(! hasCxxCtor)) { return obj; } construct_flags |= OBJECT_CONSTRUCT_FREE_ONFAILURE; return object_cxxConstructFromClass(obj, cls, construct_flags); }Copy the code

6. CLS ->instanceSize() calculates the size of the object, calloc() calculates the size, and obj->initInstanceIsa()

Objc_alloc is executed when a symbol breakpoint is set. If objc_alloc is executed, we need to investigate further. We give a printf to alloc, objC_alloc, callAlloc, _objc_rootAlloc, _objc_rootAllocWithZone, _class_createInstanceFromZone, Then perform a trial run.

The NSObject execution flow is found objc_alloc->callAlloc->_objc_rootAllocWithZone->_class_createInstanceFromZone. Our own class execution order is objc_alloc->callAlloc->alloc->objc_rootAlloc->callAlloc->_objc_rootAllocWithZone->_class_createInstanceFro mZone

8. Summarize alloC process

NSObject Execution process objc_alloc->callAlloc->_objc_rootAllocWithZone->_class_createInstanceFromZone.

Our own class execution order is objc_alloc->callAlloc->alloc->objc_rootAlloc->callAlloc->_objc_rootAllocWithZone->_class_createInstanceFro mZone