返回
OC对象原理探索:深入剖析OC对象内存分配与管理
IOS
2023-10-25 10:42:30
前言
在上一篇文章中,我们按照源码分析了一下alloc的调用流程,大致如下:
objc_msgSend(objc_getClass("NSObject"), sel_registerName("alloc"))
现在我们在objc源码中,再做一次分析alloc具体是如何调用C++底层的函数的 。
alloc的C++实现
objc源码中的alloc函数定义在objc-runtime-new.mm
文件中:
id objc_msgSend(Class cls, SEL op, ...)
{
// ... 省略其他代码 ...
if (cls == nil) {
@throw([NSInvalidArgumentException exceptionWithName:@"NSObject+Nil" reason:@"nil class" userInfo:nil]);
}
if (op == nil) {
@throw([NSInvalidArgumentException exceptionWithName:@"NSObject+Nil" reason:@"nil selector" userInfo:nil]);
}
// ... 省略其他代码 ...
struct objc_super super;
// ... 省略其他代码 ...
id (*msgSendTyped)(id, SEL, ...) = (id (*)(id, SEL, ...))objc_msgSend_stret;
// ... 省略其他代码 ...
return (*msgSendTyped)(receiver, op, &super, ...);
}
从这段代码中,我们可以看到alloc函数最终调用了objc_msgSend_stret
函数,该函数定义在objc-msg-send.mm
文件中:
extern "C" id objc_msgSend_stret(id self, SEL op, ...)
{
// ... 省略其他代码 ...
// 获取方法的实现
IMP imp = class_getMethodImplementation(cls, op);
// ... 省略其他代码 ...
// 调用方法的实现
id result = imp(self, op, ...);
// ... 省略其他代码 ...
return result;
}
通过以上分析,我们可以得知alloc函数最终调用了class_getMethodImplementation
函数获取方法的实现,然后调用该实现来分配对象。
ARC和MRC下的内存管理
在ARC(Automatic Reference Counting)下,内存管理是自动进行的,编译器会自动跟踪对象的引用计数,并在引用计数为0时释放对象。
在MRC(Manual Reference Counting)下,内存管理需要手动进行,开发人员需要自己管理对象的引用计数,并在不需要对象时手动释放对象。
ARC下的内存管理
在ARC下,编译器会自动跟踪对象的引用计数,并在引用计数为0时释放对象。例如:
// 创建一个对象
NSObject *obj = [[NSObject alloc] init];
// ... 省略其他代码 ...
// 对象不再需要,引用计数为0,编译器自动释放对象
obj = nil;
在ARC下,我们不需要手动管理对象的引用计数,编译器会自动完成这项工作。
MRC下的内存管理
在MRC下,内存管理需要手动进行,开发人员需要自己管理对象的引用计数,并在不需要对象时手动释放对象。例如:
// 创建一个对象
NSObject *obj = [[NSObject alloc] init];
// ... 省略其他代码 ...
// 对象不再需要,需要手动释放对象
[obj release];
在MRC下,我们需要自己管理对象的引用计数,并在不需要对象时手动释放对象。
总结
本文深入探索了OC对象内存分配与管理原理,从源码分析alloc的调用流程,揭秘ARC和MRC下的内存管理机制,全面解析OC对象的创建、销毁和内存管理细节,帮助你深入理解OC对象的底层实现。