#####1.测试用到的代码
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSObject *obj = [[NSObject alloc] init];
NSLog(@"%zu",class_getInstanceSize([NSObject class]));
NSLog(@"%zu",malloc_size((__bridge const void *)obj));
}
return 0;
}
//打印结果为8 16
#####2.OC转化成C/C++的实质
clang -rewrite-objc main.m -o main.cpp
将oc转成c++的代码- 在
main.cpp
全局搜索NSObject,会找到如下图的一段代码
- 通过上图的代码结构可以发现
NSObject
转化成C++
的代码结构后只有一个Class isa
的这么一个指针参数。
#####内存占用的分析
最开始的代码打印的结果分别是8
和16
。具体来分析一下这两个结果是怎么出现的。 class_getInstanceSize
结果为8
的具体实现:
首先去找一下objc
的具体底层的实现,去objc官网地址下载最新的版本。全局搜索class_getInstanceSize
方法会找到如下的代码。
size_t class_getInstanceSize(Class cls)
{
if (!cls) return 0;
return cls->alignedInstanceSize();
}
->然后跳转到"alignedInstanceSize()"方法的实现,代码如下
// Class's ivar size rounded up to a pointer-size boundary.
"这里有一行注释,说的是返回的是成员变量的内存大小"
uint32_t alignedInstanceSize() const {
return word_align(unalignedInstanceSize());
}
通过查看底层的实现
结合NSObejct
转化成C++
的代码可以很清楚的明白为何返回内存结果为8
。
malloc_size
结果为16
的具体原因
首先学过C
语言的都知道malloc
方法是分配内存空间的操作。而[[NSObject alloc] init]
就是做初始化操作,所以其中肯定存在分配内存空间的操作。所以我们找一下alloc
的具体实现。
+ (id)alloc {
return _objc_rootAlloc(self);
}
-> "_objc_rootAlloc()"方法的实现:
_objc_rootAlloc(Class cls)
{
return callAlloc(cls, false/*checkNil*/, true/*allocWithZone*/);
}
-> "callAlloc"的具体实现
callAlloc(Class cls, bool checkNil, bool allocWithZone=false)
{
#if __OBJC2__
if (slowpath(checkNil && !cls)) return nil;
if (fastpath(!cls->ISA()->hasCustomAWZ())) {
return _objc_rootAllocWithZone(cls, nil);
}
#endif
}
-> "在'callAlloc'方法中发现最终调用的是'_objc_rootAllocWithZone '方法,
然后再来查看一下"
_objc_rootAllocWithZone(Class cls, malloc_zone_t *zone __unused)
{
// allocWithZone under __OBJC2__ ignores the zone parameter
return _class_createInstanceFromZone(cls, 0, nil,
OBJECT_CONSTRUCT_CALL_BADALLOC);
}
-> "然后查看 '_class_createInstanceFromZone' 这个方法的实现"
_class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone)
{
void *bytes;
size_t size;
// Can't create something for nothing
if (!cls) return nil;
// Allocate and initialize
size = cls->alignedInstanceSize() + extraBytes;
// CF requires all objects be at least 16 bytes.
if (size < 16) size = 16;
if (zone) {
bytes = malloc_zone_calloc((malloc_zone_t *)zone, 1, size);
} else {
bytes = calloc(1, size);
}
return objc_constructInstance(cls, bytes);
}
最后在方法_class_createInstanceFromZone()
方法中看到这么一行代码if (size < 16) size = 16;
而NSObject
只有一个参数Class isa
占用8
个字节,小于16
个字节,所以返回结果是16
。
#####特别说明一下
在查询源码的时候发现好多的代码分新版和旧版,有可能在新版中查询不到想要的信息,此时需要去查询旧版的信息才可能查询到一些想要的信息。也有可能是反过来查询。这个需要根据实际情况进行查询选择。