一、选择题 ⚠️ 有单选有多选哦⚠️
1.1 在LP64下,一个指针的有多少个字节
-
A: 4
-
B: 8
-
C: 16
-
D: 64
1.2 一个实例对象的内存结构存在哪些元素
-
A:成员变量
-
B: supClass
-
C: cache_t
-
D: bit
A
1.3 下面sizeof(struct3) 大小等于
struct Struct1 { char b;// 1 int c; // 4 double a; // 8 short d; // 2}struct1;
struct Struct2 { double a; int b; char c; short d;}struct2;
struct Struct3 { double a; int b; char c; struct Struct1 str1; short d; int e; struct Struct2 str2;}struct3;-
A: 48
-
B: 56
-
C: 64
-
D: 72
C
1.4 下列代码: re1 re2 re3 re4 re5 re6 re7 re8输出结果
BOOL re1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];BOOL re2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]];BOOL re3 = [(id)[LGPerson class] isKindOfClass:[LGPerson class]];BOOL re4 = [(id)[LGPerson class] isMemberOfClass:[LGPerson class]];NSLog(@" re1 :%hhd\n re2 :%hhd\n re3 :%hhd\n re4 :%hhd\n",re1,re2,re3,re4);
BOOL re5 = [(id)[NSObject alloc] isKindOfClass:[NSObject class]];BOOL re6 = [(id)[NSObject alloc] isMemberOfClass:[NSObject class]];BOOL re7 = [(id)[LGPerson alloc] isKindOfClass:[LGPerson class]];BOOL re8 = [(id)[LGPerson alloc] isMemberOfClass:[LGPerson class]];NSLog(@" re5 :%hhd\n re6 :%hhd\n re7 :%hhd\n re8 :%hhd\n",re5,re6,re7,re8);-
A: 1011 1111
-
B: 1100 1011
-
C: 1000 1111
-
D: 1101 1111
1.5 (x + 7) & ~7 这个算法是几字节对齐
-
A: 7
-
B: 8
-
C: 14
-
D: 16
1.6 判断下列数据结构大小
union kc_t { uintptr_t bits;// 8 struct { int a;// 4 char b;// 1 };}-
A: 8
-
B: 12
-
C: 13
-
D: 16
1.7 元类的 isa 指向谁, 根元类的父类是谁
-
A: 自己 , 根元类
-
[B] B: 自己 , NSObject
-
C: 根元类 , 根元类
-
D: 根元类 , NSObject
1.8 查找方法缓存的时候发现是乱序的, 为什么? 哈希冲突怎么解决的
-
A: 哈希函数原因 , 不解决
-
B: 哈希函数原因 , 再哈希
-
C: 他存他的我也布吉岛 , 再哈希
-
D: 他乱由他乱,清风过山岗 , 不解决
1.9 消息的流程是
-
A: 先从缓存快速查找
-
B: 慢速递归查找methodlist (自己的和父类的,直到父类为nil)
-
C: 动态方法决议
-
D: 消息转发流程
1.10 类方法动态方法决议为什么在后面还要实现 resolveInstanceMethod
-
A: 类方法存在元类(以对象方法形式存在), 元类的父类最终是 NSObject 所以我们可以通过resolveInstanceMethod 防止 NSObject 中实现了对象方法!
-
B: 因为在oc的底层最终还是对象方法存在
-
C: 类方法存在元类以对象方法形式存在.
-
D: 咸吃萝卜,淡操心! 苹果瞎写的 不用管
A
二、判断题
2.1 光凭我们的对象地址,无法确认对象是否存在关联对象
- 对
- 错
2.2 int c[4] = {1,2,3,4}; int *d = c; c[2] = *(d+2)
- 对
- 错
2.3 @interface LGPerson : NSObject{ UIButton *btn } 其中 btn 是实例变量
- 对
- 错
2.4 NSObject 除外 元类的父类 = 父类的元类
- 对
- 错
2.5 对象的地址就是内存元素的首地址
- 对
- 错
对
2.6 类也是对象
- 对
- 错
三、简单题
3.1 怎么将上层OC代码还原成 C++代码 分值10分
xcrun 或 clang
3.2 怎么打开汇编查看流程,有什么好处 ? 分值10分
debug - DebugWorkflow - Always show disassembly- 查看汇编可以从更深层次了解当前函数的汇编层面的执行,为
OBJC源码分析提供信息,部分源码的执行被LLDB进行了改动,结合会变查看可以避免方向性错误,结合memory read可以更清楚的看到寄存器之间是如何让互相配合处理配合的。使用汇编查看流程可以再不确定源码出处和执行流程的情况下,跟踪内部代码,并找到出处。同时,结合符号断点的方式能够更清楚的跟踪源码实现。
3.3 x/4gx 和 p/x 以及 p *$0 代表什么意思 分值10分
- 从首地址开始,1️以8字节的形式打印4段地址
- 打印地址
- 取出
$0地址中的数据
3.4 类方法存在哪里? 为什么要这么设计? 分值10分
-
实例方法保存在类的方法列表中
-
类方法保存在元类的方法列表中
-
这样设计的好处:
- 底层不用区分类方法和对象方法,本质上都是对象方法。方法调用都可以理解为消息发送,只不过消息的接收者不一样。
- 这样设计更加的面向对象,类的一切信息都存储在元类中,对象的一切信息都存储在类中。类是元类实例化出的对象,实例对象是类实例化出的对象。存储也更符合面向对象的特点。
- OC语言早期借鉴了另一种
SmallTalk的语言,其中也是这么设计的。
3.5 方法慢速查找过程中的二分查找流程,请用伪代码实现 分值10分
3.6 ISA_MASK = 0x00007ffffffffff8ULL 那么这个 ISA_MASK 的算法意义是什么? 分值10分
ISA包含在ISA_BITFIELD中, & ISA_MASK是为了去除ISA地址两边的数据(标志位、引用计数等),拿到正确的ISA地址。
3.7 类的结构里面为什么会有 rw 和 ro 以及 rwe ? 分值10分
- class_ro_t
- read only
- 类名、方法、协议、成员变量等
- Clean memory
- 运行时不会改变
- class_rw_t
- read write
- 使用来读写数据的,在这个数据结构中存储了只有在运行时才会生成的信息。
- 可读可写
- Dirty memory
- 运行时会改变
- class_rw_ext_t
- read write extension
- 动态添加的
- 方法
- 属性
- 协议等
- 这将 class_rw_t 的体积减少了进 50%。在有需要的时候将 class_rw_ext_t 插入其中,约 90% 的类用不到这些拓展数据
Dirty memory 要比 Clean memory 昂贵的多,只要进程在运行,他就一直存在。Clean memory 可以进行移除,以节省空间;如果需要可以再从磁盘中加载。
之所以将Class的数据分成两部分,是为了尽可能的节省空间
3.8 cache 在什么时候开始扩容 , 为什么? 分值10分
- 一般情况
- 3/4
- 真机Arm64
- 7/8
- 小缓存特殊情况
- 100%
- 为什么
- 效率
3.9 objc_msgSend 为什么用汇编写 , objc_msgSend 是如何递归找到imp? 分值10分
效率高
3.10 一个类的类方法没有实现为什么可以调用 NSObject 同名对象方法 分值10分
ISA