This is the 29th day of my participation in the August More Text Challenge
In previous articles, we looked at the memory management and stack of blocks; Today we’re going to look at what a block is;
Clang analyzes the block underlying structure
No __block decorates variables
When it comes to analyzing structures, our first instinct is to use clang or xcrun to analyze CPP files;
To avoid interference from other functions, we create a block.c file with the following code:
Go to the file directory and generate the CPP file using the xcrun command:
xcrun -sdk iphonesimulator clang -arch arm64 -rewrite-objc block.c -o block.cpp
Next, open the CPP file and look at the main function, which is implemented as follows:
We removed the codes related to strong conversion and type and optimized the CPP file codes as follows:
So what is __main_block_IMPL_0? The implementation can also be found in CPP files:
You can see that __main_block_IMPL_0 is a structure; Block refers to the __main_block_IMPL_0 constructor.
A (_a) is a c++ syntax. We pass _a to the member variable a, passing _a to a;
Now, what we find is that we have an A in this structure, is this a our external parameter a? We modify the code in the main function as follows:
__main_block_IMPL_0 in the two CPP files:
This means that when we pass in the argument a, which is caught by the block, it generates a member variable at the bottom of the block; The same applies to object types, which also generate member variables;
Reanalyzing __main_block_IMPL_0 we find the detail imp.isa = &_nsConcretestackblock; The IMPl isa points to an _NSConcreteStackBlock;
As we said earlier, if a block catches external variables and is not weakly referenced, it should be a heap block; Instead, the compiler generates a stack block;
Does it generate stack blocks at compile time and then become heap blocks at run time?
Let’s look at the __main_block_IMPL_0 constructor. Its first argument is fp. When is FP called?
So first we have to figure out what is FP? Fp refers to __main_block_func_0, so what is __main_block_func_0?
__main_block_func_0 is also a function, that is, fp passes a function; And impl. FuncPtr = fp; Where fp is assigned to FuncPtr; FuncPtr is called inside main;
At the bottom, a block is a functional save of FP; So once a block is defined, if it is not called, the functional logic code is never executed;
We find in __main_block_func_0 that a comes from __cself->a(value copy), so what is the passed __cself?
__cself is the block itself; A in __main_block_IMPL_0 has the same value and different address as ain __main_block_func_0.
__block decorates a variable
In development, we often have a situation where we need to modify a in a block, so we need to modify A with __block, so we can modify a inside the block, so what does __block do that makes it possible to modify external variables?
Next, we modify the main function as follows:
Then generate its CPP file; Let’s first look at what happens to the __main_block_IMPL_0 structure:
You can see that our int a was changed to __Block_byref_a_0 *a by using __block; There is an extra line in the main function: __attribute__((__blocks__(byref))) __Block_byref_a_0 a = {(void*)0,(__Block_byref_a_0 *)&a, 0, sizeof(__Block_byref_a_0), 5}; Obviously, this is an initialization of a structure; The code is optimized as follows:
Next let’s look at __Block_byref_a_0:
__forwarding
isa
;
The __Block_byref_a_0 structure is then entered in the __main_block_IMPL_0 constructor
Then a(_A ->__forwarding) passes __forwarding in the __Block_byref_a_0 structure to the __Block_byref_a_0 member variable __Block_byref_a_0 * A;
A in __main_block_func_0 is the same as ain a = 5, they both refer to the same piece of memory (address passed, pointer assigned);
Because they all point to the same memory space, external variables can be modified inside the block;
__block generates a structure __Block_byref_a_0, and passes the address of the pointer to the block, thus achieving the purpose of modifying the same memory space.
At this point, we have a basic understanding of the underlying data structure of blocks, but we have a question: is it possible that a stack block is generated at compile time and becomes a heap block at run time? Still unresolved; Listen to our next explanation at……