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:

  • __forwardingisa;

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……