iOS内存管理

2020-03-27  本文已影响0人  CoderKK
iOS程序的内存布局(由低到高)
保留段
代码段(_TEXT)
数据段(_DATA)
堆(heap)
栈(stack)
内核区

代码段:编译之后的代码
数据段:按如下由低到高分配

栈:函数调用开销,比如局部变量。内存分配的内存空间越来越小
堆:通过alloc、malloc等动态分配的空间,分配的空间地址越来越大

Tagged Pointer

判断Tagged Pointer相关源码

#if TARGET_OS_OSX && __x86_64__
    // 64-bit Mac - tag bit is LSB
#   define OBJC_MSB_TAGGED_POINTERS 0
#else
    // Everything else - tag bit is MSB
#   define OBJC_MSB_TAGGED_POINTERS 1
#endif
#if OBJC_MSB_TAGGED_POINTERS
#   define _OBJC_TAG_MASK (1UL<<63)
#else
#   define _OBJC_TAG_MASK 1UL
#endif
static inline bool 
_objc_isTaggedPointer(const void * _Nullable ptr) 
{
    return ((uintptr_t)ptr & _OBJC_TAG_MASK) == _OBJC_TAG_MASK;
}
相关面试题

思考一下以下两段代码会发生什么事?有什么区别?

@property (strong, nonatomic) NSString *name;

dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
for (int i = 0; i < 1000; i++) {
    dispatch_async(queue, ^{
        self.name = [NSString stringWithFormat:@"abcdefghijk"];
    });
}
@property (strong, nonatomic) NSString *name;

dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
for (int i = 0; i < 1000; i++) {
    dispatch_async(queue, ^{
        self.name = [NSString stringWithFormat:@"abc"];
    });
}

第一段会报坏内存访问(EXC_BAD_ACCESS)异常,第二段正常运行
原因:第一段self.name的本质是调用[self setName:]方法,方法实质实现如下

- (void)setName:(NSString *)name{
    if (_name != name) {
        [_name release];
        _name = [name retain];
    }
}

当多个线程同时调用时,就会出现由于_name已经被释放但还继续调用[_name release]方法,造成坏内存访问,可以使用加锁方式解决该异常
第二段由于[NSString stringWithFormat:@"abc"]是个Tagged Ponter,采用的是直接赋值的方式,所以不会造成问题。

OC对象的内存管理
copy和mutableCopy
NSString NSMutableString NSArray NSMutableArray NSDictionary NSMutableDictionary
copy 浅拷贝 深拷贝 浅拷贝 深拷贝 浅拷贝 深拷贝
mutableCopy 深拷贝 深拷贝 深拷贝 深拷贝 深拷贝 深拷贝

深拷贝和浅拷贝的判断依据是有没有生成新的副本对象
总结:不可变对象的copy是浅拷贝,其他的均为深拷贝
自定义对象使用copy,要遵循NSCopying协议,实现copyWithZone:方法

ARC
上一篇下一篇

猜你喜欢

热点阅读