前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >TaggedPointer

TaggedPointer

作者头像
老沙
发布2019-09-29 15:57:47
3590
发布2019-09-29 15:57:47
举报
文章被收录于专栏:老沙课堂

先解决个问题

首先定义
代码语言:javascript
复制
@property (nonatomic, copy) NSString *test;
方法一
代码语言:javascript
复制
  for (int i = 0; i < 1000; i++) {
      dispatch_async(dispatch_get_global_queue(0, 0), ^{
          self.test = [NSString stringWithFormat:@"%@",@"123"];
      });
  }
方法二
代码语言:javascript
复制
  for (int i = 0; i < 1000; i++) {
      dispatch_async(dispatch_get_global_queue(0, 0), ^{
          self.test = [NSString stringWithFormat:@"%@",@"abababababababababababababab"];
      });
  }

运行段代码 有什么区别?现象是什么?

  • 方法一:正常运行
  • 方法二:崩溃
为什么?

查看崩溃日志

  • 坏内存访问
分析原因

test属性 setter方法实际执行以下内容

代码语言:javascript
复制
- (void)setTest:(NSString *)test {
    if (![_test isEqualToString:test]) {
        [_test release];
        _test = [test copy];
        [test release];
    }
}

由于test 修饰为nonatomic 所以是线程不安全的。当多条线程同时访问,造成多次release ,所以坏内存访问。

解决方式

修饰改为atomic 或者加锁

疑问
为什么方式一不会崩溃?

首先打印两个NSString的类型

解决疑问

正常对象都是 指针指向对象的地址, 指针指向堆内存中的地址,所以方法二会因为多线程访问而造成坏内存访问,而TaggedPointer 则不会创建内存,而是在isa指针上做手脚。在指针上存放具体值。

TaggedPointer

64位开始 引入了Tagged Pointer 技术,用于优化NSNumber、NSDate、NSString 等小对象存储

打印方式一、方式二的NSString地址

从上图可以看出 0结尾的为对象地址 因为以16位为基准 内存对齐

而方法二的明显不一样。

我们看一下objc_release的源码
代码语言:javascript
复制
objc_release(id obj)
{
    if (!obj) return;
    if (obj->isTaggedPointer()) return;
    return obj->release();
}

当obj为isTaggedPointer的时候 直接返回。所以更加验证了刚才的说法 即:用指针存值,而不是在堆中生成对象

代码语言:javascript
复制
objc_object::isTaggedPointer()
{
    return _objc_isTaggedPointer(this);
}
代码语言:javascript
复制
#   define _OBJC_TAG_MASK 1UL
static inline bool 
_objc_isTaggedPointer(const void * _Nullable ptr)
{
    return ((uintptr_t)ptr & _OBJC_TAG_MASK) == _OBJC_TAG_MASK;
}

从上面可以看出当尾数为1的时候为TaggedPointer

偶尔会出现尾数为不为1的TaggedPointer 不知道什么原因。但源码确实是这么写的。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-09-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 老沙说点事 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 先解决个问题
    • TaggedPointer
    相关产品与服务
    对象存储
    对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档