As an iOS developer, alloc init is probably one of the most common things that happens in everyday development. But do you really understand how alloc works? This paper explores the principle of OC object.

# # sample

QLPerson *person1 = [QLPerson alloc] ;
QLPerson *person2 = [person1 init];
QLPerson *person3 = [person1 init];
NSLog(@"%@--%p---%p",person1,person1,&person1);
NSLog(@"%@--%p---%p",person2,person2,&person2);
NSLog(@"%@--%p---%p",person3,person3,&person3);
Copy the code

What is the printed result?

<QLPerson: 0x600000a38390>--0x600000a38390---0x7ffeee8ffcf8
<QLPerson: 0x600000a38390>--0x600000a38390---0x7ffeee8ffcf0
<QLPerson: 0x600000a38390>--0x600000a38390---0x7ffeee8ffce8
Copy the code

Only &person1, &person2, &person3 are different, which are three consecutive addresses, and the other printed addresses are 0x600000a38390. Let’s explore the process of its principle.

## explore methods #### method 1 add breakpoints:QLPerson *person1 = [QLPerson alloc] ;inxcodeAt breakpoint, press and holdcontrolKey, mouse click down arrowstep into instructionInto the underlying1, toobjc_alloc 2, continue to click the arrow, comelibobjc.A.dylib objc_alloc 3,_objc_rootAllocWithZone

#### Method two through assembly, find symbol display assembly:Xcode-->Debug-->Debug Workflow-->Always Show Disassembly

You can see it in the assemblysymbol stub for: objc_alloc, hold down the Control key and click the down arrow to enterobjc_allocIn, repeat the steps of method 1 without further elaboration. #### Add symbol breakpoint:objc_alloc._objc_rootAllocWithZone

The above three methods are to explore the thinking process of Alloc. Next, we will use the source code provided by Apple to explore the process of Alloc and achieve the purpose through source code debugging. First of all, objC source code can be obtained from Apple Source, which is difficult to compile. Please refer to the compilation process of Cooci. After completing the above steps, we started to explore the alloc process: 1. Add test target to objC source project, and add the following code in main.m:

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        QLPerson *person1 = [QLPerson alloc];
//        QLPerson *person2 = [person1 init];
//        QLPerson *person3 = [person1 init];
        
//        NSLog(@"%@--%p---%p",person1,person1,&person1);
//        NSLog(@"%@--%p---%p",person2,person2,&person2);
//        NSLog(@"%@--%p---%p",person3,person3,&person3);
        NSLog(@"%@",person1);
    
    }
    return 0;
}
Copy the code

Command + left to enter nsobject. mm, call source code as follows:

+ (id)alloc { return _objc_rootAlloc(self); } id _objc_rootAlloc(Class cls) { return callAlloc(cls, false/*checkNil*/, true/*allocWithZone*/); } 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

Select objc-Runtime-new.mm

NEVER_INLINE id _objc_rootAllocWithZone(Class cls, malloc_zone_t *zone __unused) { // allocWithZone under __OBJC2__ ignores the zone parameter return _class_createInstanceFromZone(cls, 0, nil, OBJECT_CONSTRUCT_CALL_BADALLOC); } static ALWAYS_INLINE id _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

After adding breakpoints to the source code above, I summarized the debugging process into a diagram:

Text flow: + alloc –_objc_rootAlloc –callAlloc –_objc_rootAllocWithZone –_class_createInstanceFromZone Open up, relate)

## Summary: This article is a preliminary exploration of oc objects, only the oc object alloc process, init process will be described in the next chapter. If you have different opinions, please leave a message.