About the alloc

Alloc is the oc object instantiation method, you must have written many times in your daily work, such as:

LGPerson *person1 = [LGPerson alloc] ;
LGPerson *person2 = [[LGPerson alloc] init];
LGPerson *person3 = [[LGPerson allocWithZone:nil] init];
LGPerson *person4 = [LGPerson new];
Copy the code

So the question is, what’s the difference between these allocs?

Let’s talk about what each of these do, and then we’ll break down the process. We say it from the bottom up:

  • The new method is the same as alloc and init, alloc allocates memory and init is called to initialize, and new allocates memory and init is called to initialize, in one step
  • NSZone is a method used by Apple to allocate and free memory. It is not an object, but uses C structure to store memory information about the object. The allocWithZone method is a legacy of history and is no longer used. There is no difference between allocWithZone and alloc, as will be seen in the source code parsing
  • Finally, person1 and person2. The difference between person1 and person2 is that person1 allocates memory and is not initialized, while Person allocates memory and is initialized

And it’s not hard to see that all of these things end up with alloc, so let’s explore what alloc does.

The source code to prepare

  • Apple openSource openSource.apple.com/ has the source code for Objc for Mac
  • For compiling the source code, please refer to ObjC4-779.1 source code compilation and debugging in Mr. Cooci’s article macOS 10.15

The source code to track

  • So we can visually see that alloc is calling _objc_rootAlloc, and allocWithZone is calling _objc_rootAllocWithZone, and then we can trace the calls inside those two functions

  • And you can see here why alloc and allocWithZone are no different, because they both call callAlloc internally, right

So let’s take a look at what callAlloc ends up implementing internally

  • Breakpoint debugging calls _objc_rootAllocWithZone

  • Then we call _class_createInstanceFromZone internally

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(extrabize); if (outAllocatedSize) *outAllocatedSize = size; id obj; if (zone) { // 2; AllocWithZone Specifies the memory pool obj = (id)malloc_zone_calloc((malloc_zone_t *)zone, 1, size); } else { // 2; Obj = (id)calloc(1, size); } if (slowpath(! obj)) { if (construct_flags & OBJECT_CONSTRUCT_CALL_BADALLOC) { return _objc_callBadAllocHandler(cls); } return nil; } // 3: associate CLS class with obj pointer (isa) 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
  • Now you can see that in this method you calculate the required memory, along with byte alignment, call calloc to allocate memory, and finally associate CLS with ISA through initInstanceIsa
  • This completes the process, and the alloc object is created and allocated

conclusion

Now you can comb through the process Alloc->_objc_rootAlloc ->callAlloc->_objc_rootAllocWithZone->_class_createInstanceFromZone->(instanceSize, calloc, initInst) anceIsa)