-
iOS 两个容易混淆的函数:class_getInstanceSize & malloc
-
示例代码如下:
#import <Foundation/Foundation.h> #import <objc/runtime.h> #import <malloc/malloc.h> struct NSObject_IMPL { Class isa; }; struct Person_IMPL{ struct NSObject_IMPL NSOBJECT_IVARS; int _age; int _height; int _no; }; @interface Person : NSObject { //年龄 int _age; //身高 int _height; //学号 int _no; } @end @implementation Person @end int main(int argc, char * argv[]) { @autoreleasepool { // Setup code that might create autoreleased objects goes here. NSObject *obj = [[Person alloc] init]; /** sizeof 是针对传入的类型作计算 sizeof 是运算符,不是函数,编绎之后就能立马确定结果。编绎后根据传入的类型能算出结果,随后类似宏定义编绎后替换源代码一样,将结果与 sizeof 表达式进行替换。 */ NSLog(@"%zd",sizeof(struct Person_IMPL)); size_t size1 = class_getInstanceSize([Person class]); size_t size2 = malloc_size((__bridge const void *)(obj)); NSLog(@"%zd",size1); NSLog(@"%zd",size2); } return 0; }
输出结果:
24
24
32查看苹果的相关源码(源码地址:https://github.com/apple-oss-distributions/libmalloc/tags),相关源码如下:
-
在 malloc.c 文件中搜索 “calloc(size” 可得:
void * calloc(size_t num_items, size_t size) { return _malloc_zone_calloc(default_zone, num_items, size, MZ_POSIX); }
-
跳转 _malloc_zone_calloc 方法,可得:
MALLOC_NOINLINE static void * _malloc_zone_calloc(malloc_zone_t *zone, size_t num_items, size_t size,malloc_zone_options_t mzo) { if (zone == default_zone && !lite_zone) { // Eagerly resolve the virtual default zone to make the zone version // check accurate zone = malloc_zones[0]; } if (os_unlikely(malloc_instrumented || malloc_check_start || malloc_logger || zone->version < 13)) { return _malloc_zone_calloc_instrumented_or_legacy(zone, num_items, size, mzo); } // zone versions >= 13 set errno on failure so we can tail-call return zone->calloc(zone, num_items, size); }
-
/* Buckets sized {16, 32, 48, ..., 256} */
小结:
-
class_getInstanceSize 返回的实际上就是结构体所有成员变量的大小,通过上面代码的测试,它的作用与 sizeof 计算一个结构体所有成员大小的结果是一致的。
-
malloc 是通过 calloc(1,size) 方法最终算出需要给对象分配多大的内存空间。此处传入的 size 通过源码也能发现,实际上就是等于 class_getInstanceSize 返回的大小。而他们最终分配的内存空间大小差异就在于:malloc 还多了 calloc 方法这一层的处理。
-
malloc 是在堆内存中进行操作,堆内存的内存分配也是遵循了内存对齐的原则。这里跟 bucketSize 的大小有关,即分配的内存大小必须是16的倍数。因此,传入的 size 是24,经过 calloc 这一层处理之后,返回的就是 32.
-
-
-
结论:
-
创建一个实例对象,至少需要多少内存?
#import <objc/runtime.h> class_getInstanceSize([NSObject class]);
-
创建一个实例对象,实际上分配了多少内存?
#import <malloc/malloc.h> malloc_size((__bridge const void *)obj);
-
网友评论