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

TaggedPointer

作者头像
老沙
发布于 2019-09-29 07:57:47
发布于 2019-09-29 07:57:47
37000
代码可运行
举报
文章被收录于专栏:老沙课堂老沙课堂
运行总次数:0
代码可运行

先解决个问题

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

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

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

查看崩溃日志

  • 坏内存访问
分析原因

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
- (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
代码运行次数:0
运行
AI代码解释
复制
objc_release(id obj)
{
    if (!obj) return;
    if (obj->isTaggedPointer()) return;
    return obj->release();
}

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
objc_object::isTaggedPointer()
{
    return _objc_isTaggedPointer(this);
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#   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 删除。

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
iOS - 老生常谈内存管理(五):Tagged Pointer
在objc4源码中,我们经常会在函数中看到Tagged Pointer。Tagged Pointer究竟是何方神圣?请开始阅读本文。
师大小海腾
2020/04/24
2K0
iOS - 老生常谈内存管理(五):Tagged Pointer
iOS_Tagged Pointer是什么,结构
64位CPU下:指针8位 -> 值8位 (一共需要16位)(未使用Tagged Pointer情况下)
mikimo
2022/07/20
5060
iOS_Tagged Pointer是什么,结构
iOS property的多线程问题解析
先解析提供的要素: a.nonatomic的NSArray属性; b.异步执行,gcd并发队列; c.多个block,对myNumberArr的多次读写操作;
落影
2020/08/25
1.2K0
iOS property的多线程问题解析
OC底层探索27-TaggedPointOC底层探索27-TaggedPoint
在objc的源码分析中,经常看到这个isTaggedPointer判断,这个TaggedPoint有什么特别呢?
用户8893176
2021/08/09
5020
OC底层探索27-TaggedPointOC底层探索27-TaggedPoint
iOS-内存管理(一)
heap: which is created objc and block by alloc will store in heap area
Wilbur-L
2020/12/18
1K0
iOS-内存管理(一)
iOS系统源码思考:对象的引用计数存储在哪里?--从runtime源码得到的启示
iOS开发者都知道OC里面的内存管理是通过对象的引用计数来管理的,或手动MRC,或自动ARC,有些操作可以让引用计数加1,有些可以减1,一旦一个对象的引用计数为0,就回收内存了。
陈满iOS
2018/09/10
6.1K0
iOS系统源码思考:对象的引用计数存储在哪里?--从runtime源码得到的启示
锁的使用以及底层原理
我们知道,@synchronized是一把互斥锁(互斥锁保证在任何时刻都只能有一个线程访问该对象),它通过大括号来作为加锁、解锁的标识。
拉维
2021/04/16
6930
iOS底层—OC对象的本质与isa
我们已经学习了对象的初始化、内存对齐等内容。这篇文章将深入学习探究对象的本质、对isa进行分析。
CC老师
2022/01/11
6100
iOS底层—OC对象的本质与isa
GCDAsyncSocket 在 iOS15 出现 -[_NSThreadPerformInfo dealloc] 崩溃排查笔记
本文会通过对 NSThread 的原理进行分析,对 iOS 15 开始出现的 [_NSThreadPerformInfo dealloc] 相关崩溃进行定位,并提供相应的解决方案
酷酷的哀殿
2022/03/14
4.1K1
GCDAsyncSocket 在 iOS15 出现 -[_NSThreadPerformInfo dealloc] 崩溃排查笔记
Objc 对象的今生今世
在面向对象编程中,我们每天都在创建对象,用对象描述着整个世界,然而对象是如何从孕育到销毁的呢?
一缕殇流化隐半边冰霜
2018/08/30
7520
Objc 对象的今生今世
Objective-C内存管理原理探究(一)
MelonTeam
2018/01/04
1.1K0
Objective-C内存管理原理探究(一)
从一道网易面试题浅谈 Tagged Pointer
因为在 并行队列 DISPATCH_QUEUE_CONCURRENT 中异步 dispatch_async 对 target属性进行赋值,就会导致 target 已经被 release了,还会执行 release。这就是向已释放内存对象发送消息而发生 crash 。
零式的天空
2022/03/25
3480
内卷吧! iOS开发君
前段时间因为课程需要 , 我出了一套iOS考试试卷 想着VIP大家做得非常不错. 带着分享的精神也开源了出来 一套iOS底层试卷-我想和你分享 结果反响巨大! 很多靓仔靓女纷纷私聊我....大致分为以下两种:
CC老师
2022/01/12
3630
iOS - 老生常谈内存管理(四):内存管理方法源码分析
建议去掘金查看本文,带目录方便阅读。 《iOS - 老生常谈内存管理(四):内存管理方法源码分析》
师大小海腾
2020/04/24
2.3K0
《Effective Objective-C 》干货三部曲(三):技巧篇
继上一篇《Effective Objective-C 》超级干货三部曲(二):规范篇之后,本篇即是三部曲的第三篇:技巧篇。本篇作为三部曲的最终篇,归纳讲解的是本书中关于Objective-C开发的技巧性知识。
用户2932962
2018/08/30
8040
《Effective Objective-C 》干货三部曲(三):技巧篇
浅谈 KVO 的实现原理
KVO 全称 KeyValueObserving 是 Objective-C 对观察者模式(Observer Pattern)的实现;KVO 提供一种机制,当指定的对象的属性被修改后,则对象就会接受收到通知。简单的说就是每次指定的被观察的对象的属性被修改后,KVO 就会自动通知相应的观察者了。
s_在路上
2018/09/30
1.9K0
iOS-底层原理36:内存优化(一) 野指针探测
下面是Mach异常 与 UNIX信号 的转换关系代码,来自 xnu 中的 bsd/uxkern/ux_exception.c
conanma
2021/10/28
2.5K0
iOS疑难Crash的寄存器赋值追踪排查技术
我们会借助一些崩溃日志收集库来定位和排查线上的崩溃信息,但是有些崩溃堆栈所提供的信息有限又不是必现崩溃,很难直观排查出问题的所在。这里我给大家分享一个采用寄存器赋值追踪的技术来排查和分析崩溃日志的技巧。话不多说先看案例:
欧阳大哥2013
2021/04/01
3.5K3
iOS疑难Crash的寄存器赋值追踪排查技术
深入剖析 iOS 性能优化
在集合里数据量小的情况下时间复杂度对于性能的影响看起来微乎其微。但如果某个开发的功能是一个公共功能,无法预料调用者传入数据的量时,这个复杂度的优化显得非常重要了。
用户7451029
2020/06/16
1.7K0
深入剖析 iOS 性能优化
KVO详解(二)
上篇文章中我介绍了KVO的简单用法以及KVO的实现细节,为了加深对KVO的理解,我决定从头到尾介绍一下如何自定义KVO。
拉维
2021/03/25
7600
KVO详解(二)
相关推荐
iOS - 老生常谈内存管理(五):Tagged Pointer
更多 >
LV.0
这个人很懒,什么都没有留下~
加入讨论
的问答专区 >
1Java工程师擅长4个领域
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
    本文部分代码块支持一键运行,欢迎体验
    本文部分代码块支持一键运行,欢迎体验