1、从 main 函数开始

我们先在在 main 函数中打一个断点,并且再添加一个 _objc_init 的符号断点,方便看调用栈状态。
image.png
加载流程如下图
image.png

2、alloc探索

我们先在main函数里面新建一个 ZLPerson 类,然后在 alloc 处下一个断点
image.png
然后我们使用 control + in 命令进入之后可以看出
image.png

alloc 调用的其实是 objc_alloc 函数

3、探索 libObjc 源码

然后我们把源码挂载到我们项目当中,然后通过断点分析,得到以下流程:
image.png

让我们配合源码信息进行分析

3.1 callAlloc源码分析

  1. static ALWAYS_INLINE id
  2. callAlloc(Class cls, bool checkNil, bool allocWithZone=false)
  3. {
  4. #if __OBJC2__
  5. if (slowpath(checkNil && !cls)) return nil;
  6. if (fastpath(!cls->ISA()->hasCustomAWZ())) {
  7. return _objc_rootAllocWithZone(cls, nil);
  8. }
  9. #endif
  10. // No shortcuts available.
  11. if (allocWithZone) {
  12. return ((id(*)(id, SEL, struct _NSZone *))objc_msgSend)(cls, @selector(allocWithZone:), nil);
  13. }
  14. return ((id(*)(id, SEL))objc_msgSend)(cls, @selector(alloc));
  15. }

fastpath(x)表示x很可能不为0;slowpath(x)表示x很可能为0。——这里表示cls大概率是有值的,编译器可以不用每次都读取 return nil 指令,都是希望编译器进行优化。

3.2 核心创建实例 _class_createInstanceFromZone 分析

  1. static ALWAYS_INLINE id
  2. _class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone,
  3. int construct_flags = OBJECT_CONSTRUCT_NONE,
  4. bool cxxConstruct = true,
  5. size_t *outAllocatedSize = nil)
  6. {
  7. ASSERT(cls->isRealized());
  8. // Read class's info bits all at once for performance
  9. bool hasCxxCtor = cxxConstruct && cls->hasCxxCtor();
  10. bool hasCxxDtor = cls->hasCxxDtor();
  11. bool fast = cls->canAllocNonpointer();
  12. size_t size;
  13. // 获取cls的实例内存大小,extraBytes为0
  14. size = cls->instanceSize(extraBytes);
  15. if (outAllocatedSize) *outAllocatedSize = size;
  16. id obj;
  17. if (zone) {
  18. obj = (id)malloc_zone_calloc((malloc_zone_t *)zone, 1, size);
  19. } else {
  20. // 根据实例size开辟内存
  21. obj = (id)calloc(1, size);
  22. }
  23. if (slowpath(!obj)) {
  24. if (construct_flags & OBJECT_CONSTRUCT_CALL_BADALLOC) {
  25. return _objc_callBadAllocHandler(cls);
  26. }
  27. return nil;
  28. }
  29. if (!zone && fast) {
  30. // 将cls和是否有c++析构器传入给initInstanceIsa,实例化isa
  31. obj->initInstanceIsa(cls, hasCxxDtor);
  32. } else {
  33. // Use raw pointer isa on the assumption that they might be
  34. // doing something weird with the zone or RR.
  35. obj->initIsa(cls);
  36. }
  37. if (fastpath(!hasCxxCtor)) {
  38. return obj;
  39. }
  40. construct_flags |= OBJECT_CONSTRUCT_FREE_ONFAILURE;
  41. return object_cxxConstructFromClass(obj, cls, construct_flags);
  42. }