docs: image url

This commit is contained in:
FantasticLBP
2026-01-02 10:28:57 +08:00
parent 7ac7513900
commit 7843661458
29 changed files with 719 additions and 719 deletions

View File

@@ -28,7 +28,7 @@ block(1, 2);
用指令`xcrun --sdk iphoneos clang -arch arm64 ViewController.m -rewrite-objc -o ViewController-arm64.cpp` 转为 c++
<img src="./../assets/BlockViaClangC.png" style="zoom:25%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/BlockViaClangC.png" style="zoom:25%">
`ViewController.m` 的 `viewDidLoad` 函数为 `_I_ViewController_viewDidLoad`
@@ -240,7 +240,7 @@ struct __ViewController__viewDidLoad_block_desc_0 {
}
```
<img src="./../assets/MockBlockDemo.png" style="zoom:25%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/MockBlockDemo.png" style="zoom:25%">
@@ -254,7 +254,7 @@ struct __ViewController__viewDidLoad_block_desc_0 {
<img src="./../assets/block-structure.png" style="zoom:40%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/block-structure.png" style="zoom:40%">
@@ -279,11 +279,11 @@ printBlock();
用 `xcrun --sdk iphoneos clang -arch arm64 ViewController.m -rewrite-objc -o ViewController-arm64.cpp` 转换为 c++
<img src="./../assets/SimpleBlockExploreDemo.png" style="zoom:40%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/SimpleBlockExploreDemo.png" style="zoom:40%">
概括如下:
<img src="./../assets/SimpleSimpleBlockCaptureStructure.png" style="zoom:40%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/SimpleSimpleBlockCaptureStructure.png" style="zoom:40%">
@@ -301,7 +301,7 @@ printAgeBlock();
用指令 `xcrun --sdk iphoneos clang -arch arm64 ViewController.m -rewrite-objc -o ViewController-arm64.cpp` 转换为 c++ 代码
<img src="./../assets/AutoVariableCaptureByBlock.png" style="zoom:25%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/AutoVariableCaptureByBlock.png" style="zoom:25%">
代码分析:
@@ -338,7 +338,7 @@ printInfoBlock();
用指令 `xcrun --sdk iphoneos clang -arch arm64 ViewController.m -rewrite-objc -o ViewController-arm64.cpp` 转换为 c++ 代码
<img src="./../assets/StaticVariableCaptureByBlock.png" style="zoom:25%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/StaticVariableCaptureByBlock.png" style="zoom:25%">
@@ -379,7 +379,7 @@ age is 28, height is 176
用指令 `xcrun --sdk iphoneos clang -arch arm64 ViewController.m -rewrite-objc -o ViewController-arm64.cpp` 转换为 c++ 代码
<img src="./../assets/GlobalVariableWillNotCaptureByBlock.png" style="zoom:25%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/GlobalVariableWillNotCaptureByBlock.png" style="zoom:25%">
@@ -460,7 +460,7 @@ block 截获变量可以分为:
用指令 `xcrun --sdk iphoneos clang -arch arm64 Person.m -rewrite-objc -o Person-arm64.cpp` 转换为 c++ 代码
<img src="./../assets/BlockWillCaptureMethodSelfVariable.png" style="zoom:25%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/BlockWillCaptureMethodSelfVariable.png" style="zoom:25%">
@@ -582,13 +582,13 @@ static void __Person__testBlockCapture_block_func_0(struct __Person__testBlockCa
我们知道 block 可以看成是一个 oc 对象,所以它有类型,写个 Demo1 验证下
<img src="./../assets/BlockClassType.png" style="zoom:40%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/BlockClassType.png" style="zoom:40%">
也就是说: `__NSGlobalBlock__` -> `NSBlock` -> `NSObject`。
继续验证Demo2
<img src="./../assets/OCBlockType.png" style="zoom:40%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/OCBlockType.png" style="zoom:40%">
同时利用指令 `xcrun --sdk iphoneos clang -arch arm64 ViewController.m -rewrite-objc -o ViewController-arm64.cpp` 转换为 c++
@@ -613,7 +613,7 @@ block 的类型可以通过 isa 或者 class 方法查看,最终都是继承
这3种 block 在内存中的排布如下图:
<img src="./../assets/block-memorylayout.png" style="zoom:40%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/block-memorylayout.png" style="zoom:40%">
@@ -625,7 +625,7 @@ Demo
由于 ARC 默认会做一些优化,为了彻底的研究 block我们将工程的 ARC 关掉Build Setting 里 Automatic Reference Counting 设置为 No
<img src="./../assets/OCStackBlockCrash.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/OCStackBlockCrash.png" style="zoom:30%">
分析:
@@ -643,7 +643,7 @@ Demo
当 `__NSStackBlock__` 调用 `copy` 方法后会变为 `__NSMallocBlock__`。如下图:
<img src="./../assets/FixStackBlockIssueWithCopy.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/FixStackBlockIssueWithCopy.png" style="zoom:30%">
@@ -699,7 +699,7 @@ int main(int argc, const char * argv[]) {
MRC 下 block 作为函数的返回值是比较危险的。在方法内部,也就是栈上定义的 block函数调用结束后可能一些相关数据就释放了存在潜在风险。
<img src="./../assets/BlockAsFunctionReturnValueIsDangerous.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/BlockAsFunctionReturnValueIsDangerous.png" style="zoom:30%">
@@ -707,7 +707,7 @@ MRC 下 block 作为函数的返回值是比较危险的。在方法内部,也
MRC 下如果函数返回值是 block且 block 内做了 auto 变量捕获的逻辑,编译器会报错:`Returning block that lives on the local stack`。此时 block 应该为 `__NSStackBlock__`
<img src="./../assets/MRCCompileFailedWhenBlockCaptureAutoVarsiableAndAsReturnValue.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/MRCCompileFailedWhenBlockCaptureAutoVarsiableAndAsReturnValue.png" style="zoom:30%">
即使编译器不报错,也存在很大风险,因为 block 创建在栈上,函数返回后栈内存可能被回收,导致后续访问野指针。
@@ -738,7 +738,7 @@ HelloBlock generateBlock(void) {
另外的改法是,在 Build Setting 中改为 ARC看看
<img src="./../assets/CompileWillCallCopyWhenBlockCaptureAutoVarsiableAndAsReturnValueInARC.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/CompileWillCallCopyWhenBlockCaptureAutoVarsiableAndAsReturnValueInARC.png" style="zoom:30%">
也就是说ARC 模式下,当 block 捕获了 auto 变量并且作为函数返回值的时候ARC 会自动调用 copy 方法,将 `__NSStackBlock__` 变为 `__NSMallocBlock__`
@@ -819,11 +819,11 @@ ARC 下:如果 block 调用 copy 方法,则 block 仍旧为 `__NSMallocBloc
MRC 下,栈内捕获了 auto 变量的 block 为 `__NSStackBlock__`
<img src="./../assets/LocalBlockInMRC.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/LocalBlockInMRC.png" style="zoom:30%">
改为 ARC
<img src="./../assets/LocalBlockInARCWillCallCopy.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/LocalBlockInARCWillCallCopy.png" style="zoom:30%">
@@ -862,31 +862,31 @@ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), di
ARC 下block 对象捕获了 auto 外部变量,是一种 `__NSMallocBlock__`,捕获的对象将会在 block 销毁后销毁
<img src="./../assets/ARCObjectWillReleasedWhenLeaveScope.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/ARCObjectWillReleasedWhenLeaveScope.png" style="zoom:30%">
MRC 下block 对象捕获了 auto 外部变量,是一种 `__NSMallocBlock__`,因为是 MRC所以需要手动管理内存。会发现对象将在离开作用域后立马销毁不会被 block 所捕获。
<img src="./../assets/MRCObjectCannotCaptureByMallocBlock.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/MRCObjectCannotCaptureByMallocBlock.png" style="zoom:30%">
MRC对 block 加 copy变为 `__NSMallocBlock__` 呢?
<img src="./../assets/MRCObjectWillReleaseWhenBlockIsReleased.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/MRCObjectWillReleaseWhenBlockIsReleased.png" style="zoom:30%">
ARC 下对 block 引用的对象加 `__weak` 修饰呢?
<img src="./../assets/ARCWeakObjectWillReleaseWhenLeaveScope.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/ARCWeakObjectWillReleaseWhenLeaveScope.png" style="zoom:30%">
用指令 `xcrun --sdk iphoneos clang -arch arm64 main.m -rewrite-objc -fobjc-arc -fobjc-runtime=ios-8.0.0 -o main-arm64.cpp` 转换为 c++ 进行分析看看。注意,因为 weak 涉及运行时,需要在 clang 后添加 runtime 参数
<img src="./../assets/WeakObjectCapturedByBlock.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/WeakObjectCapturedByBlock.png" style="zoom:30%">
如果对 Person 不加 `__weak` 修饰block 结构体内部将会是`__strong`。
<img src="./../assets/StrongObjectCapturedByBlock.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/StrongObjectCapturedByBlock.png" style="zoom:30%">
@@ -930,13 +930,13 @@ static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_objec
Demo1:
<img src="./../assets/ObjectWillReleaseWhenGCDTimeout.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/ObjectWillReleaseWhenGCDTimeout.png" style="zoom:30%">
说明ARC 环境下GCD 的 block 会自动被拷贝到堆上 `__NSMallocBlock__`,堆上的 block 会对使用的对象进行 copy所以 person 引用计数+1则在 GCD block 执行完毕后才 release
Demo2
<img src="./../assets/WeakObjectWillReleaseWhenLeaveScope.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/WeakObjectWillReleaseWhenLeaveScope.png" style="zoom:30%">
- 栈空间上的 block 是不会对对象进行保命的(不管是 ARC 还是 MRC都不调用 retain、copy 方法)。
- ARC 下, block 如果访问了 auto, static 变量,则属于 `__NSStackBlock__`ARC 下用强指针指向,则会变为 `__NSMallocBlock__ 堆上的 block 是会对对象进行保命的。GCD 的 block 会自动拷贝到堆上,属于 `\__NSMallocBlock__`,也会对对象进 行 copy 保命。
@@ -950,13 +950,13 @@ Demo2
Demo3
<img src="./../assets/DoubleGCDMainQueueTaskObjectWillReleaseAfterTotalTime.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/DoubleGCDMainQueueTaskObjectWillReleaseAfterTotalTime.png" style="zoom:30%">
因为 GCD 是给 MainQueue 添加任务的所以是串行2个任务前后按照3s、1s 后打印。由于最晚的一个任务是访问强指针对象,所以不会释放。等到 GCD 全部执行完后Person 才释放。
Demo4
<img src="./../assets/DoubleGCDMainQueueTaskObjectWillReleaseAfterStrongReference.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/DoubleGCDMainQueueTaskObjectWillReleaseAfterStrongReference.png" style="zoom:30%">
@@ -1130,7 +1130,7 @@ test 和 test2 的本质区别
Demo3
<img src="./../assets/VisitReleasedStackBlockWillCrash.png" style="zoom:30%" />
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/VisitReleasedStackBlockWillCrash.png" style="zoom:30%" />
为什么上面的代码会 crash
@@ -1195,7 +1195,7 @@ Demo3
Demo4
<img src="./../assets/BlockAssignIsValueAssign.png" style="zoom:30%" />
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/BlockAssignIsValueAssign.png" style="zoom:30%" />
分析:
@@ -1391,7 +1391,7 @@ MyBlock block = ^{
转为 C++
<img src="./../assets/BlockChangeVariableUse__Block.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/BlockChangeVariableUse__Block.png" style="zoom:30%">
```c++
struct __Block_byref_age_0 {
@@ -1435,7 +1435,7 @@ block 内部的函数在修改 age 的时候其实就是通过 `__main_block_imp
<img src="./../assets/block-forwarding.png" style="zoom:40%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/block-forwarding.png" style="zoom:40%">
@@ -1447,7 +1447,7 @@ QA为什么`__block` 变量的 `__Block_byref_age_0` 结构体并不在 block
看个有趣的例子,验证下 __block 的效果
<img src="./../assets/Block__BLOCKAssignObject.png" style="zoom:30%" />
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/Block__BLOCKAssignObject.png" style="zoom:30%" />
转换成 c++ 可以看到
@@ -1492,7 +1492,7 @@ __attribute__((__blocks__(byref))) __Block_byref_num2_0 num2 = {(void*)0,(__Bloc
对` __block` 修饰的对象clang 转换为 c++ 后如下:
<img src="./../assets/BlockChangeVariableUse__BlockOnObject.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/BlockChangeVariableUse__BlockOnObject.png" style="zoom:30%">
@@ -1505,7 +1505,7 @@ __attribute__((__blocks__(byref))) __Block_byref_num2_0 num2 = {(void*)0,(__Bloc
注意:
<img src="./../assets/NSMutableArrayDonotNeedBlockToUseArray.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/NSMutableArrayDonotNeedBlockToUseArray.png" style="zoom:30%">
@@ -1575,7 +1575,7 @@ int main(int argc, const char * argv[]) {
我们将断点设置到 NSLog 这里,打印出自定义结构体 `__main_block_impl_0` 中的 age 。
<img src="./../assets/Block-variableAddress.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/Block-variableAddress.png" style="zoom:30%">
```c
// 0x0000000105231f70
@@ -1750,7 +1750,7 @@ in block: age = 28, address is 0x600000464938
<img src="./../assets/BlockChangeOuterValue.png" style="zoom:100%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/BlockChangeOuterValue.png" style="zoom:100%">
分析:
@@ -1804,7 +1804,7 @@ in block: age = 28, address is 0x600000464938
通过 Demo1 和 Demo2 总结下:` __forwarding` 的作用是什么?为什么这么设计
<img src="./../assets/block_forwarding.png" style="zoom:15%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/block_forwarding.png" style="zoom:15%">
@@ -1903,7 +1903,7 @@ Tips实现 block 拷贝及其捕获对象的函数是 `_Block_copy`,工作
Demo0
<img src="./../assets/BlockVariableDemo0.png" style="zoom:100%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/BlockVariableDemo0.png" style="zoom:100%">
可以看到:
@@ -1912,17 +1912,17 @@ Demo0
Demo1
<img src="./../assets/BlockVariableDemo1.png" style="zoom:100%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/BlockVariableDemo1.png" style="zoom:100%">
<img src="./../assets/block-strong-object-memoery.png" style="zoom:30%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/block-strong-object-memoery.png" style="zoom:30%">
Demo2
<img src="./../assets/BlockVariableDemo2.png" style="zoom:100%">
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/BlockVariableDemo2.png" style="zoom:100%">
<img src="./../assets/block-weak-object-memoery.png" style="zoom:30%" >
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/block-weak-object-memoery.png" style="zoom:30%" >
@@ -2121,7 +2121,7 @@ __attribute__((__blocks__(byref))) __Block_byref_p_0 p = {
看个 Demo
<img src="./../assets/blockCaptureStrongObjectError.png" style="zoom:40%" />
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/blockCaptureStrongObjectError.png" style="zoom:40%" />
可以看到 block 放在堆上的时候(被抢指针指向、作为返回值)的时候,如果 block 内部访问了强指针指向的对象,则会发生循环引用。
@@ -2164,7 +2164,7 @@ Person *p = [[Person alloc] init];
<img src="./../assets/WeakSolveBlockRetainCycle.png" style="zoom:40%" />
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/WeakSolveBlockRetainCycle.png" style="zoom:40%" />
@@ -2186,7 +2186,7 @@ p.block();
`__unsafe_retained` 因为不安全所以不推荐,`__block` 因为使用繁琐,且必须等到调用 block 才会释放内存所以不推荐。ARC 下最佳用 `__weak`
![](./../assets/block_object_cycle.png)
![](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/block_object_cycle.png)