The alloc method is a necessary step to create an object. We usually use alloc directly to create an object. So how to implement the underlying alloc method? What methods are called during this process? What does each method do? So with that in mind how is alloc actually implemented at the bottom?

The preparatory work

  • This article explores the underlying principle of the main method is: source code, assembly, breakpoint debugging, LLDB debugging
  • Apple source
    • opensource.apple.com/
    • opensource.apple.com/tarballs/
  • This article sample code address (including compiled source code) : gitee.com/jrcode/ios_…

Alloc flow analysis

Locate source code

LGPerson *p1 = [LGPerson alloc];
Copy the code
  • Place a breakpoint at the above code location, execute to the breakpoint location, and holdcontrol+step into, enter assembly

  • So here we see the call firstobjc_allocMethod, but it is difficult to follow the process, in which case we can use symbolic breakpoints
  • Add sign breakpointobjc_allocAnd continue to execute

  • As can be seen from the running results
    • objc_allocMethods in thelibobjc.A.dylibIn the dynamic library, i.eobjcThe source code
    • The next call is_objc_rootAllocWithZoneandobjc_msgSend

Look at the alloc process through the source code

  • It’s been locatedobjc_allocMethod, search directly in the source code projectobjc_alloc(, locate theobjc_allocMethod implementation location inNSObject.mmIn the file
// Calls [cls alloc].
id
objc_alloc(Class cls)
{
    return callAlloc(cls, true/*checkNil*/.false/*allocWithZone*/);
}
Copy the code
  • As can also be seen from the comments in the code above, the callallocMethod is actually calledobjc_allocAnd then callcallAllocmethods
// Call [cls alloc] or [cls allocWithZone:nil], with appropriate
// shortcutting optimizations.
static ALWAYS_INLINE id
callAlloc(Class cls, bool checkNil, bool allocWithZone=false)
{
#if __OBJC2__
    if(slowpath(checkNil && ! cls))return nil;
    if(fastpath(! cls->ISA()->hasCustomAWZ())) {return _objc_rootAllocWithZone(cls, nil);
    }
#endif

    // No shortcuts available.
    if (allocWithZone) {
        return ((id(*) (id, SEL, struct _NSZone *))objc_msgSend)(cls, @selector(allocWithZone:), nil);
    }
    return ((id(*) (id, SEL))objc_msgSend)(cls, @selector(alloc));
}
Copy the code
  • In the above method, there is no way to determine what is being called_objc_rootAllocWithZoneorobjc_msgSend, how to determine the execution process next?
    • Method one: because what we’re debugging worksobjcSource code, so you can directly add breakpoints in the source code to debug the execution process
    • Method two: assembly and process combine symbolic breakpoints
    • Note: Since breakpoints may also be called on objects created during system initialization, you need to disable breakpoints when executing to**[LGPersion alloc]**To enable the breakpoint

Dynamic debugging

First use method two: assembly and flow combine symbol breakpoints

  • To perform to[LGPerson alloc]At the breakpoint of thecontrol+step intoEnter the assembly
  • Lower sign breakpointobjc_alloc, and continue to execute toobjc_alloc
  • Step down, and you can see what’s calledobjc_msgSendRather than_objc_rootAllocWithZone
  • Perform toobjc_msgSend, read the current register, you can see, here is calledallocmethods
    • Register read: Reads the current register information
    • Register Read X0: The X0 register holds the message receiver
    • Register read x1: The SEL is stored in register X1

  • From the above debugging flow, you can see the calling flow:
    • objc_alloc
    • msgSend
    • alloc

Continue with method one: source add breakpoint debugging process

  • To perform to[LGPerson alloc]Add breakpoints to the source code below, and then execute the flow

  • Through breakpoint debugging, you can determine the source code call flow:
    • objc_alloc
    • callAlloc
    • return ((id(*)(id, SEL))objc_msgSend)(cls, @selector(alloc));
    • alloc
    • _objc_rootAlloc
    • callAlloc
    • _objc_rootAllocWithZone
    • _class_createInstanceFromZone
      • InstanceSize: Calculates the memory usage of objects
      • Calloc: Opens up memory and returns the address
      • InitInstanceIsa: initializes the ISA and associates it with the class
      • return obj; Return object address

Summary: Alloc call flowchart