mirror of
https://github.com/NohamR/knowledge-kit.git
synced 2026-05-25 04:17:17 +00:00
update: content update
This commit is contained in:
@@ -182,7 +182,7 @@ NSLog(@"%p %p %@", obj, &obj, obj);
|
||||
|
||||
### 为什么有 Tagged Pointer
|
||||
|
||||
现状:一般,存放 NSNumber、NSDate 这类变量的时候,本身占用的内存大小常常不需要8个字节。4字节带符号的证书可以达到2^31= 2147483648,99% 的情况都能满足了。因此为了更高效、更节省空间,用一个看似是指针的计数,来存储数据,且在 Runtime 侧判断了,节省了消息机制那一套冗长的流程,Tagged Pointer cover 一些小数据的场景,cover 不了则申请堆内存。
|
||||
现状:一般,存放 NSNumber、NSDate 这类变量的时候,本身占用的内存大小常常不需要8个字节。4字节带符号的整数可以达到2^31= 2147483648,99% 的情况都能满足了。因此为了更高效、更节省空间,用一个看似是指针的计数,来存储数据,且在 Runtime 侧判断了,节省了消息机制那一套冗长的流程,Tagged Pointer cover 一些小数据的场景,cover 不了则申请堆内存。
|
||||
|
||||
|
||||
|
||||
@@ -1505,7 +1505,7 @@ weak_table_t 结构如下:
|
||||
struct weak_entry_t {
|
||||
DisguisedPtr<objc_object> referent; // 被弱引用的对象
|
||||
|
||||
// 引用该对象的对象列表,联合。 引用个数小于4,用 inline_referrers 数组。 用个数大于4,用动态数组 weak_referrer_t *referrers
|
||||
// 引用该对象的对象列表,联合。 引用个数小于4,用 inline_referrers 数组。 个数大于4,用动态数组 weak_referrer_t *referrers
|
||||
union {
|
||||
struct {
|
||||
weak_referrer_t *referrers; // 弱引用该对象的对象指针地址的hash数组
|
||||
@@ -1551,10 +1551,32 @@ struct weak_entry_t {
|
||||
|
||||
#### 存 weak 对象
|
||||
|
||||
声明一个 `__weak` 对象
|
||||
|
||||
```objective-c
|
||||
{
|
||||
id __weak obj = strongObj;
|
||||
}
|
||||
```
|
||||
|
||||
LLVM转换成对应的代码
|
||||
|
||||
```objective-c
|
||||
id __attribute__((objc_ownership(none))) obj1 = strongObj;
|
||||
```
|
||||
|
||||
相应的会调用
|
||||
|
||||
```objective-c
|
||||
id obj ;
|
||||
objc_initWeak(&obj,strongObj);
|
||||
objc_destoryWeak(&obj);
|
||||
```
|
||||
|
||||
上 Demo
|
||||
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/ObjcStoreWeakWhenUseWeak.png" style="zoom:30%" />
|
||||
|
||||
|
||||
|
||||
可以看到当一个 weak 指针被赋值的时候,底层调用了 `objc_initWeak`,跟踪查看 objc 源码
|
||||
|
||||
```c++
|
||||
@@ -2273,7 +2295,7 @@ weak_clear_no_lock(weak_table_t *weak_table, id referent_id)
|
||||
|
||||
- object_remove_assocations(obj):去除该对象相关的关联属性(Category 添加的)
|
||||
|
||||
- obj->clearDeallocating():清空引用技术表和弱引用表,将 weak 引用设置为 nil
|
||||
- obj->clearDeallocating():清空引用计数表和弱引用表,将 weak 引用设置为 nil
|
||||
|
||||
继续看看 object_cxxDestruct 方法内部细节。
|
||||
|
||||
@@ -2574,7 +2596,7 @@ struct FinishARCDealloc : EHScopeStack::Cleanup {
|
||||
|
||||
#### LLVM + Runtime 共同协作的结果
|
||||
|
||||
LLVM 编译器前端 clang 在编译阶段,自动帮我们给对象加了 release、retain、autorelease 的代码(比如在一个大括号内的代码,生命的对象,在大括号将要结束的时候会自动加 `[person release] 之类的代码`)。
|
||||
LLVM 编译器前端 clang 在编译阶段,自动帮我们给对象加了 release、retain、autorelease 的代码(比如在一个大括号内的代码,声明的对象,在大括号将要结束的时候会自动加 `[person release] 之类的代码`)。
|
||||
|
||||
ARC 中禁止手动调用 retain/release/retainCount/dealloc 方法。
|
||||
|
||||
@@ -4093,6 +4115,27 @@ IMP Caching 比其他方法快2倍。
|
||||
|
||||
## 典型的内存问题
|
||||
|
||||
### 使用NSArray 保存weak对象,会有什么问题?
|
||||
Foundation 中数组在元素被添加的时候(这里的数组 指平常使用的 NSArray 和 NSMutableArray )会强引用持有,就算使用 `__weak` 修饰也没有用,导致一些奇特的内存泄漏和循环引用问题。
|
||||
|
||||
`-(NSValue *)valueWithNonretainedObject:(nullable id)anObject;`
|
||||
|
||||
`NSPointerArray` 提供 `strongObjectsPointerArray` 和 `weakObjectsPointerArray`工厂,weakObjectsPointerArray 就是我们需要的弱引用数组方法。
|
||||
|
||||
NSHashTable 和 NSMapTable
|
||||
|
||||
```
|
||||
// 弱应用对象
|
||||
NSMapTable *map = [NSMapTable weakToWeakObjectsMapTable];
|
||||
[map setObject:dog forKey:@"first"];
|
||||
|
||||
// 弱应用对象
|
||||
NSHashTable *hashTable = [NSHashTable weakObjectsHashTable];
|
||||
[hashTable addObject:dog];
|
||||
```
|
||||
|
||||
|
||||
|
||||
### OC 中有没有不对内存进行强持有的集合类型?
|
||||
|
||||
`NSHashMap`、`NSMapTable` 都可以描述 key、value 的内存修饰。
|
||||
|
||||
Reference in New Issue
Block a user