前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >swift底层探索 01 - 类初始化&类结构swift底层探索 01 - 类初始化&类结构

swift底层探索 01 - 类初始化&类结构swift底层探索 01 - 类初始化&类结构

作者头像
用户8893176
发布于 2021-08-09 03:28:13
发布于 2021-08-09 03:28:13
89900
代码可运行
举报
文章被收录于专栏:小黑娃Henry小黑娃Henry
运行总次数:0
代码可运行

探索swift可以通过:源码调试Sil文件xcode断点调试这些方式来进行探索,除Sil文件这种方式其他的都会在本文中出现。OC底层探索01-找到底层探索的钥匙会有解释。

探索路径同样是参考oc的探索路径,先从类开始。

类初始化

1. 使用Xcodel断点调试
  • 创建一个简单的类,开启汇编断点
  • 1步骤就是__allocation_initswift对象初始化入口
  • 通过2步骤可以进入下一步(下断点,按住control+↓)
  • swift_allocObject是初始化第二步
  • 下断点,按住control+↓进入下一步
  • swift_slowAlloc是初始化第三步
  • 下断点,按住control+↓进入下一步
  • malloc_zone_malloc是初始化第四步,在这一步完成内存的分配,最终完成alloc步骤
2. 使用源码调试

现在通过源码调试来验证一下之前的论点。源码编译方式Swift-5.3.1 源码编译.

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
static HeapObject *_swift_allocObject_(HeapMetadata const *metadata,
                                       size_t requiredSize,
                                       size_t requiredAlignmentMask) {
  assert(isAlignmentMask(requiredAlignmentMask));
  //swift慢速创建流程
  auto object = reinterpret_cast<HeapObject *>(
      swift_slowAlloc(requiredSize, requiredAlignmentMask));
  //为创建好的内存赋值
  new (object) HeapObject(metadata);

  SWIFT_LEAKS_START_TRACKING_OBJECT(object);

  SWIFT_RT_TRACK_INVOCATION(object, swift_allocObject);

  return object;
}

void *swift::swift_slowAlloc(size_t size, size_t alignMask) {
  void *p;
  
  //一般使用 8字节对齐 
  //#  define MALLOC_ALIGN_MASK 15
  if (alignMask <= MALLOC_ALIGN_MASK) {
#if defined(__APPLE__)
    //apple的类会进入这里
    p = malloc_zone_malloc(DEFAULT_ZONE(), size);
#else
    p = malloc(size);
#endif
  } else {
  //大于16字节对齐的情况,比较少见
    size_t alignment = (alignMask == ~(size_t(0)))
                           ? _swift_MinAllocationAlignment
                           : alignMask + 1;
    p = AlignedAlloc(size, alignment);
  }
  if (!p) swift::crash("Could not allocate memory.");
  return p;
}
  • 根据源码也可以跟到具体的流程
  • alignMask <= MALLOC_ALIGN_MASK进入这个判断可以看出swift类一般使用的是8字节对齐
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#define malloc_zone_malloc(zone,size) malloc(size)
  • malloc_zone_malloc只是一个宏定义,最终调用malloc
3. 初始化流程图

类结构 - HeapObject结构

1. 编译器断点
  • 在进行类创建,源码调试的时候发现swift的类结构是这样的。和oc比起来是有一些不同的。我们换种方式看看.
2. lldb
  • 相比于OC不同的是,除了第一位之外,还将引用计数当做第二个参数保存到对象中
3. 源码查看

swift对象继承自**HeapObject**

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
struct HeapObject {
  /// This is always a valid pointer to a metadata object.
  HeapMetadata const *metadata;

//#define SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS       \
  InlineRefCounts refCounts
  SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS;
  
  ...
}
swift-类的结构图

HeapMetadata结构

如果说metaData相比于oc对象中的isa的而言的话,应该要包含isa,superclass,cache_t,date等类的信息。我们就来看看HeapMetadata结构都有些什么呢~

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//相当于宏定义 
using HeapMetadata = TargetHeapMetadata<InProcess>

//template 模板类
struct TargetHeapMetadata : TargetMetadata<InProcess>{
    。。。
}

struct TargetMetadata<InProcess>{
    StoredPointer Kind; //用来区分是什么类型的原数据 

//一个相关的方法
    getObjCClassObject() const {
    return reinterpret_cast<Class>(
      const_cast<TargetClassMetadata<InProcess>*>(
        getClassObject()));
  }
}
  • TargetHeapMetadata是一个模板类,想要了解内部结构需要继续向下查看
  • <InProcess>类似于泛型,限制泛型的具体类型
  • 没有看到其他相关定义,只能借助其他方式来查看getClassObject
借助getClassObject方法查看HeapMetadata结构
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//获取类对象
  Metadata::getClassObject() const {
    switch (getKind()) {
    case MetadataKind::Class: {
      return static_cast<const ClassMetadata *>(this);
    }
    //如果是类,指针强转为ClassMetadata
    case MetadataKind::ObjCClassWrapper: {
      auto wrapper = static_cast<const ObjCClassWrapperMetadata *>(this);
      return wrapper->Class;
    }
      return nullptr;
    }
  }
  • 我们发现将当前指针强转为ClassMetadata。指针可以强转则表示内部结构是相同的,我们可以转换角度去查看ClassMetadata.
ClassMetadata
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
using ClassMetadata = TargetClassMetadata<InProcess>;
struct TargetClassMetadata : TargetAnyClassMetadata<Runtime> {
    ClassFlags Flags;
    uint32_t InstanceAddressPoint;
    uint32_t InstanceSize;
    ...
}

struct TargetAnyClassMetadata : TargetHeapMetadata
{
  ConstTargetMetadataPointer  Superclass;
  TargetPointer CacheData[2];
  StoredSize Data;
  ...
}
元类结构图

swift类结构.png

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/12/11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
iOS底层—OC对象的本质与isa
我们已经学习了对象的初始化、内存对齐等内容。这篇文章将深入学习探究对象的本质、对isa进行分析。
CC老师
2022/01/11
5730
iOS底层—OC对象的本质与isa
Objective-C内存管理原理探究(一)
MelonTeam
2018/01/04
1.1K0
Objective-C内存管理原理探究(一)
Swift底层-对象&结构&属性
pushq %rbp //很明显,往下读pushq movl 参数入栈和传递
Wilbur-L
2021/03/07
1.1K0
Swift底层-对象&结构&属性
iOS-Swift 结构体与类
在 Swift 的标准库中,绝大多数的公开类型都是结构体,而枚举和类只占很小一部分。比如 Bool、Int、Double、 String、Array、Dictionary 等常见类型都是结构体。
CC老师
2022/01/14
1.4K0
iOS-Swift 结构体与类
面试驱动技术之 - isa && 元类 && 函数调用
以MNPerson为例,里面的成员变量有不同类型是,比如int、double、NSString 类型,假如在C/C++ 中用数组存储,显然是不太合理的
小蠢驴打代码
2019/01/28
9410
面试驱动技术之 - isa && 元类 && 函数调用
OC底层探索04-探索对象内存大小OC底层探索04-探索对象内存大小
所有的类在OC中最终都会编译为objc_object(在这个问题中可以看做父类),其中包含一个isa指针,所以需要再加上8字节。
用户8893176
2021/08/09
7000
OC底层探索04-探索对象内存大小OC底层探索04-探索对象内存大小
OC底层探索03-常用的alloc,init,new到底做了什么?OC底层探索03-常用的alloc,init,new到底做了什么?
想要一探alloc是如何申请了内存空间的,就需要使用上篇中提到的objc源码了。废话不多说,打开源码,加上断点,一步步开始调试: 此处有两种可能,简述流程省略代码:
用户8893176
2021/08/09
8340
OC底层探索03-常用的alloc,init,new到底做了什么?OC底层探索03-常用的alloc,init,new到底做了什么?
OC底层探索08-基于objc4-781类结构分析OC底层探索08-基于objc4-781类结构分析
提到缓存那么cache面缓存的是什么呢:属性还方法?其实很好猜测,平时开发中使用最多的就是方法,因为只有方法才会引起变化。下面会通过两种方式进行验证这个猜测。
用户8893176
2021/08/09
3060
OC底层探索08-基于objc4-781类结构分析OC底层探索08-基于objc4-781类结构分析
OC类的原理探究(二)——方法的缓存
上面的代码中,如果我们覆写了该类的allocWithZone方法,那么就会走到第31行的逻辑;不过一般而言我们是不会自己去覆写allocWithZone方法的,所以一般都会走第8~28行的逻辑。
拉维
2021/03/10
5510
OC类的原理探究(二)——方法的缓存
OC底层探索25-深入浅出BlockOC底层探索25-深入浅出Block
在2.2中出现了值拷贝,而且在block中也不允许使用修改捕获参数,想过要block内部修改就需要__block声明变量。
用户8893176
2021/08/09
5330
OC底层探索25-深入浅出BlockOC底层探索25-深入浅出Block
OC底层探索19-weak和assign区别浅谈OC底层探索19-weak和assign区别浅谈
weak 只可以修饰对象。如果修饰基本数据类型,编译器会报错-“Property with ‘weak’ attribute must be of object type”。 assign 可修饰对象,和基本数据类型。当需要修饰对象类型时,MRC时代使用unsafe_unretained。当然,unsafe_unretained也可能产生野指针,所以它名字是"unsafe_”。
用户8893176
2021/08/09
9830
OC底层探索19-weak和assign区别浅谈OC底层探索19-weak和assign区别浅谈
【iOS底层】 类的结构分析
这里要注意的是,在new版本的源码中,objc_class继承自objc_object,在之前的旧版本中,isa指针直接定义在objc_class中,其中OC中的NSObject在编译到底层的时候都会转变成相应的结构体objc_object
CC老师
2022/01/11
3530
OC底层探索13-基于objc4-818的cache_t结构探索OC底层探索13-基于objc4-818的cache_t结构探索
在OC底层探索09-cache_t实现原理探索中已经对cache缓存的机制做了介绍,但是这文章是基于objc4-781来探索的。技术更新的太快了,在objc4-818中cache_t的结构又发生了很大的变化。与此同时缓存的过程中也有一些小的优化。
用户8893176
2021/08/09
3300
OC底层探索13-基于objc4-818的cache_t结构探索OC底层探索13-基于objc4-818的cache_t结构探索
OC对象原理(二)
上面的代码中,如果我们覆写了该类的allocWithZone方法,那么就会走到第31行的逻辑;不过一般而言我们是不会自己去覆写allocWithZone方法的,所以一般都会走第8~28行的逻辑。
拉维
2021/10/20
7470
OC底层探索09-cache_t实现原理探索OC底层探索09-cache_t实现原理探索
在OC底层探索06-isa本身藏了多少信息你知道吗?分析了isa。 在OC底层探索08-基于objc4-781类结构分析中分析了bits;
用户8893176
2021/08/09
4120
OC底层探索09-cache_t实现原理探索OC底层探索09-cache_t实现原理探索
swift底层探索 07 -内存管理(refCount&weak&unowned)swift底层探索 07 -内存管理(refCount&weak&unowned)
提到内存管理在iOS开发中,就不得不提ARC(自动引用技术)。本文主要讨论的就是ARC在swift中是如何存储、计算,以及循环引用是如何解决的。 [toc]
用户8893176
2021/08/09
1.1K0
swift底层探索 07 -内存管理(refCount&weak&unowned)swift底层探索 07 -内存管理(refCount&weak&unowned)
swift底层探索 06 - 指针简单使用swift底层探索 06 - 指针简单使用
如果在lldb中需要获取值类型的地址,直接使用po、p、v都是无法获取地址的,只能转为指针后才可以获取,如图一。
用户8893176
2021/08/09
7170
swift底层探索 06 - 指针简单使用swift底层探索 06 - 指针简单使用
ios 底层原理 : 类与类结构分析
类的分析 类的分析主要是分析 isa 的走向与继承关系 准备 创建两个类 1.继承自 NSObject 的 LGPerson @interface LGPerson : NSObject { NSString *hobby; } @property(nonatomic,copy)NSString * lg_name; - (void)sayHello; + (void)sayBye; @end @implementation LGPerson - (void)sayHello { } +
conanma
2021/10/28
6470
iOS-底层原理36:内存优化(一) 野指针探测
下面是Mach异常 与 UNIX信号 的转换关系代码,来自 xnu 中的 bsd/uxkern/ux_exception.c
conanma
2021/10/28
2.4K0
IOS底层原理之NSObject的结构
在OC程序中,我们知道NSObject是“万物之源”,所有的类的都继承自NSObject,我们疑惑的是在OC的底层NSObject是什么样的?
CC老师
2022/01/12
7090
IOS底层原理之NSObject的结构
推荐阅读
相关推荐
iOS底层—OC对象的本质与isa
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档