Skip to content

Commit e0f8750

Browse files
author
Draveness
committed
Fixed images
1 parent 93fad93 commit e0f8750

File tree

1 file changed

+12
-12
lines changed

1 file changed

+12
-12
lines changed

objc/自动释放池的前世今生.md

+12-12
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
## 从 main 函数开始
1414

1515
`main` 函数可以说是在整个 iOS 开发中非常不起眼的一个函数,它很好地隐藏在 `Supporting Files` 文件夹中,却是整个 iOS 应用的入口。
16-
![objc-autorelease-main](media/14628459785637/objc-autorelease-main.png)
16+
![objc-autorelease-main](../images/objc-autorelease-main.png)
1717

1818
`main.m` 文件中的内容是这样的:
1919

@@ -39,7 +39,7 @@ $ clang -rewrite-objc main.m
3939

4040
在生成了一大堆警告之后,当前目录下多了一个 `main.cpp` 文件
4141

42-
![objc-autorelease-main-cpp](media/14628459785637/objc-autorelease-main-cpp.png)
42+
![objc-autorelease-main-cpp](../images/objc-autorelease-main-cpp.png)
4343

4444
> 这里删除了 `main` 函数中其他无用的代码。
4545
@@ -53,7 +53,7 @@ $ clang -rewrite-objc main.m
5353

5454
`main.cpp` 中查找名为 `__AtAutoreleasePool` 的结构体:
5555

56-
![objc-autorelease-main-cpp-struct](media/14628459785637/objc-autorelease-main-cpp-struct.png)
56+
![objc-autorelease-main-cpp-struct](../images/objc-autorelease-main-cpp-struct.png)
5757

5858
```objectivec
5959
struct __AtAutoreleasePool {
@@ -108,7 +108,7 @@ void objc_autoreleasePoolPop(void *ctxt) {
108108

109109
`AutoreleasePoolPage` 是一个 C++ 中的类:
110110

111-
![objc-autorelease-AutoreleasePoolPage](media/14628459785637/objc-autorelease-AutoreleasePoolPage.png)
111+
![objc-autorelease-AutoreleasePoolPage](../images/objc-autorelease-AutoreleasePoolPage.png)
112112

113113
它在 `NSObject.mm` 中的定义是这样的:
114114

@@ -138,23 +138,23 @@ class AutoreleasePoolPage {
138138
139139
自动释放池中的 `AutoreleasePoolPage` 是以**双向链表**的形式连接起来的:
140140
141-
![objc-autorelease-AutoreleasePoolPage-linked-list](media/14628459785637/objc-autorelease-AutoreleasePoolPage-linked-list.png)
141+
![objc-autorelease-AutoreleasePoolPage-linked-list](../images/objc-autorelease-AutoreleasePoolPage-linked-list.png)
142142
143143
> `parent` 和 `child` 就是用来构造双向链表的指针。
144144
145145
#### 自动释放池中的栈
146146
147147
如果我们的一个 `AutoreleasePoolPage` 被初始化在内存的 `0x100816000 ~ 0x100817000` 中,它在内存中的结构如下:
148148
149-
![objc-autorelease-page-in-memory](media/14628459785637/objc-autorelease-page-in-memory.png)
149+
![objc-autorelease-page-in-memory](../images/objc-autorelease-page-in-memory.png)
150150
151151
其中有 56 bit 用于存储 `AutoreleasePoolPage` 的成员变量,剩下的 `0x100816038 ~ 0x100817000` 都是用来存储**加入到自动释放池中的对象**。
152152
153153
> `begin()` 和 `end()` 这两个类的实例方法帮助我们快速获取 `0x100816038 ~ 0x100817000` 这一范围的边界地址。
154154
155155
`next` 指向了下一个为空的内存地址,如果 `next` 指向的地址加入一个 `object`,它就会如下图所示**移动到下一个为空的内存地址中**:
156156
157-
![objc-autorelease-after-insert-to-page](media/14628459785637/objc-autorelease-after-insert-to-page.png)
157+
![objc-autorelease-after-insert-to-page](../images/objc-autorelease-after-insert-to-page.png)
158158
159159
> 关于 `hiwat` 和 `depth` 在文章中并不会进行介绍,因为它们并不影响整个自动释放池的实现,也不在关键方法的调用栈中。
160160
@@ -187,7 +187,7 @@ int main(int argc, const char * argv[]) {
187187
188188
而当方法 `objc_autoreleasePoolPop` 调用时,就会向自动释放池中的对象发送 `release` 消息,直到第一个 `POOL_SENTINEL`:
189189
190-
![objc-autorelease-pop-stack](media/14628459785637/objc-autorelease-pop-stack.png)
190+
![objc-autorelease-pop-stack](../images/objc-autorelease-pop-stack.png)
191191
192192
### <a id='objc_autoreleasePoolPush'></a>objc_autoreleasePoolPush 方法
193193
@@ -315,7 +315,7 @@ void objc_autoreleasePoolPop(void *ctxt) {
315315
316316
我们一般都会在这个方法中传入一个哨兵对象 `POOL_SENTINEL`,如下图一样释放对象:
317317
318-
![objc-autorelease-pop-stack](media/14628459785637/objc-autorelease-pop-stack.png)
318+
![objc-autorelease-pop-stack](../images/objc-autorelease-pop-stack.png)
319319
320320
#### 对 objc_autoreleasePoolPop 行为的测试
321321
@@ -339,11 +339,11 @@ int main(int argc, const char * argv[]) {
339339

340340
在代码的这一行打一个断点,因为这里会调用 `autorelease` 方法,将字符串加入自动释放池:
341341

342-
![objc-autorelease-breakpoint-main](media/14628459785637/objc-autorelease-breakpoint-main.png)
342+
![objc-autorelease-breakpoint-main](../images/objc-autorelease-breakpoint-main.png)
343343

344344
当代码运行到这里时,通过 lldb 打印出当前 `hotPage` 中的栈内容:
345345

346-
![objc-autorelease-print-pool-content](media/14628459785637/objc-autorelease-print-pool-content.png)
346+
![objc-autorelease-print-pool-content](../images/objc-autorelease-print-pool-content.png)
347347

348348
1. 通过 `static` 方法获取当前 `hotPage`
349349
2. 打印 `AutoreleasePoolPage` 中的内容
@@ -352,7 +352,7 @@ int main(int argc, const char * argv[]) {
352352

353353
然后将字符串 `@"Draveness-Suffix"` 的指针传入 `pop` 方法,测试 `pop` 方法能否传入非哨兵参数。
354354

355-
![objc-autorelease-pop-string](media/14628459785637/objc-autorelease-pop-string.png)
355+
![objc-autorelease-pop-string](../images/objc-autorelease-pop-string.png)
356356

357357
再次打印当前 `AutoreleasePoolPage` 的内容时,字符串已经不存在了,这说明**`pop` 方法传入非哨兵参数是可行的**,只是我们一般不会传入非哨兵对象。
358358

0 commit comments

Comments
 (0)