iOS Tagged Pointer

先看两段代码:
第一段:

@property (nonatomic, strong) NSString *name;
- (void)test1 {
    dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);
    for (int i = 0; i < 1000; i++) {
        dispatch_async(queue, ^{
            self.name = [NSString stringWithFormat:@"abcde"];
        });
    }
}

第二段:

@property (nonatomic, strong) NSString *name;
- (void)test2 {
    dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);
    for (int i = 0; i < 1000; i++) {
        dispatch_async(queue, ^{
            self.name = [NSString stringWithFormat:@"abcdefghjsfdasdfas"];
        });
    }
}

结论:
第一段代码运行没什么问题;第二段代码运行崩溃,报EXC_BAD_ACCESS,坏内存。

分析:
由于不管是否是在ARC环境下,还是在MRC环境下,底层都是转化成MRC进行编译的。所以对self.name进行赋值相当于下面代码:

- (void)setName:(NSString *)name {
    if (_name != name) {
        id pre = _name;
        
        // 1.先保留新值
        [name retain];
        
        // 2.再进行赋值
        _name = name;
        
        // 3.释放旧值
        [pre release];
    }
}

因为释放旧值是在多条线程同步进行的,所以就会出现当前内存已经被释放了的情况下,接着又被重新释放一次,所以就会导致坏内存的情况出现;但为啥第一段代码不会出错呢?

我们接下来看下两段字符串的对象类型及内存地址:


对比.png

通过控制台打印的日志,可以看出有一个是TaggedPointer的类型。
接下来可以参考深入理解 Tagged Pointer这篇博客

Tagged Pointer 是一个能够提升性能、节省内存的有趣的技术。

  • Tagged Pointer 专门用来存储小的对象,例如 NSNumber 和 NSDate(后来可以存储小字符串)
  • Tagged Pointer 指针的值不再是地址了,而是真正的值。所以,实际上它不再是一个对象了,它只是一个披着对象皮的普通变量而已。
  • 它的内存并不存储在堆中,也不需要 malloc 和 free,所以拥有极快的读取和创建速度。
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 这篇文章是参考很多资料才写出来的,有部分内容这几位写的都很详细到位,所以就直接拷贝了,这里向这几位作者学习:深入理...
    晨寂阅读 7,222评论 3 25
  • Tagged Pointer是什么 我们知道,通常情况下,定义一个变量所占用的内存是与CPU的位数有关,比如NSI...
    米嘉勒阅读 993评论 1 3
  • Tagged Pointer特点:1.Tagged Pointer专门用来存储小的对象,例如NSNumber和NS...
    Bauyin89阅读 164评论 0 0
  • 测试显示缺陷的存在 测试可以显示缺陷的存在,但不能证明系统不存在缺陷。测试可以减少软件中存在未被发现缺陷的可能...
    云层_阅读 851评论 1 14
  • 昨夜的星空很美,今日的你很远。 你记得你上学时的遗憾吗?是考试?是时间?还是一个故事一个人? 我想我的是一朵花。 ...
    舞W清阅读 322评论 0 1