The classification of the block
- Create a block.c file
#include "stdio.h"
int main(a){
int a = 18;
void(^block)(void) = ^ {printf("LG_Cooci - %d",a);
};
block(a);return 0;
}
Copy the code
- Open the terminal to the current file path
- Input order
Xcrun-sdk iphonesimulator clang-s-rewrite-objc-fobjc-arc-fobjc-Runtime =ios-14.4 block.c
- Generates a.cpp file with the same name
- This is the code for the corresponding block
- So this is the structure of the block
-
Here we find an int a, which is generated if the block captures an external variable, or if no external member variable is captured.
-
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _a, int flags=0) : A (_a) is a little bit weird because we’ve actually done the assignment to a = _a.
-
Isa = isa stack block, because it’s still compilation, it’s not really running, so the stack block here isa heap block that needs to be looked at
-
Function storage and call
- 1. At the beginning there was a function method
__main_block_func_0
- 2. Methods are called when a block is created
__main_block_impl_0
Pass in the previous function method as the first argument, called pt, and saveimpl.FuncPtr = fp;
.Call block) - > FuncPtr
This is where the block starts calling the function method that we just put in there. - 3. Block calls
__main_block_func_0
Passing in a parameter__cself
So this is the block,int a = __cself->a; // bound by copy
Here we take the value of a in the block and assign it to a temporary variable and print it.
Function analysis of __block
- Add a __block
- Recompile view
The type of discovery has changed. Int A becomes__Block_byref_a_0 *a
- So we’re going to take the memory address of A, and we’re going to initialize the structure. The first value of the structure is 0, the second value is the memory address of A, and the third value is the memory size of 18 lengths.
*__forwarding
Store the memory address of A.
- Block is created when the body of the mechanism
__Block_byref_a_0 a
Is passed in for saving
- A = a forwarding
- When a block is called, the value a is the address, and when the address is assigned, the address of the temporary variable is the same as before, and the pointer is assigned.
Conclusion: __block generates a __Block_byref_a_0 structure that lets the block capture the address values of the member variables, rather than simply the values, and place the address values of the variables that the block does not recognize. The function of modifying a memory address is complete.
Test and Debug process
- Write a simple block
- Open assembly debugging
- Notice that objc_retainBlock is entered here
- Block_copy is entered
See libclosure-79 for the underlying source code
- 1. The underlying structure of a block is this structure
- 1. Isa indicates the type of block to which isa is directed
- 2. Flags is a flag
- 3. Reserver is process data
- 4. Invoke stores the calling function
- 5. Descriptor Other related descriptions
- If it’s freed, if it’s a global block, it returns otherwise it goes to the next step.
_Block_copy
Block creation is compiled as a stack block and becomes a heap block only after block_copy is executed. When the runtime discovers that an external variable has been captured, it captures as much memory as it needs to
Apply for a memory space, copy the contents of the stack block, become a heap block
Here we re-mark the bitheap block
- Block_descriptor_1 *descriptor;
This is an optional argument for contiguous memory, and the data structure varies depending on the block type.
- If the type is Block_descriptor_2 there are copy and dispose methods, Function
How do I make Block_descriptor_2
- Find that the Block_descriptor_2 is obtained by panning the Block_descriptor_1 size
- Same thing for Block_descriptor_3,
- Case picture Introduction
CPP analyzes the entire process
- Write a simple block in the viewController.
- After the terminal is turned into a CPP file, the execution of the block is analyzed
- Create a block
- A block that generates such a structure
- Look at desc and see that the memory space was assigned to it when the block was created
- Copy function and dispose function
Copy actually calls the _Block_object_assign function,
- The correlation processing of captured variables, that is, different types of member variables are captured, which is done differently here
- BLOCK_FIELD_IS_OBJECT: common object type
BLOCK_FIELD_IS_OBJECT
Address pointer assignment after arc system function processing. - BLOCK_FIELD_IS_BLOCK: Block type. Block_copy operation is performed to save the address pointer assignment of this block object.
Here is the __weak, __block modifier, _Block_byref_copy
- If it is not a normal object, the reference count +1,
copy->forwarding = copy;
src->forwarding = copy;
The variable forwarding is the same as the variable forwarding in my block, so the two are the same thing.
- The __Block_byref_objc1_0 object modified by __block is last converted to this type
- Looking at the CPP file, the structure looks like this
- Isa = 8 bytes
- forwarding 8
- flags 4
- size 4
- Two functions 8 + 8
- objc1
Once the structure is created, byref_keep = is the __Block_byref_id_object_copy_131 function
Block_objc_assign is called again
That’s where it’s called, +40 bytes translation is just fine__Block_byref_objc1_0
Objc1 in the structure
Recursively one call here. Therefore, it is concluded that block captures variables differently depending on their type. The release of a block, byref_destroy, is done differently depending on the type.