Block technology is very popular and convenient in iOS development, but a slight carelessness can cause references to be unable to be freed, resulting in memory leaks. So how do you know which Block is holding an object and causing a memory leak?

One solution is to use Xcode’s Debug Memory Graph to view all lifetime objects in the current process while the program is running. This allows debugging to discover objects that should be freed but are not. To determine which objects are suspected of memory leaks.

When you click on an object, the right side can see the memory allocation of the object and the situation of the reference, so that you can further track and confirm the object is held and referenced by who is not released normally.

The black lines in the figure above are sequences where objects are strongly referenced.

Getting back to the subject, you can see in the figure above that the ViewController2 object is held by a **__NSMallocBlock__**, but you can only see the memory address of the Block object (upper right). To see the implementation code for this Block, enter the following information in the LLDB console:

(lldb) dis -s *(void**)(0x600002f51110+16)
MyLoadTest`__27-[ViewController2 loadView]_block_invoke:
    0x10c79c080 <+0>:  pushq  %rbp
    0x10c79c081 <+1>:  movq   %rsp, %rbp
    0x10c79c084 <+4>:  subq   $0x40, %rsp
    0x10c79c088 <+8>:  movq   %rdi, -0x8(%rbp)
    0x10c79c08c <+12>: movq   %rdi, %rax
    0x10c79c08f <+15>: movq   $0x0, -0x10(%rbp)
    0x10c79c097 <+23>: leaq   -0x10(%rbp), %rcx
    0x10c79c09b <+27>: movq   %rdi, -0x20(%rbp)
Copy the code

The dis-S address in the above instructions is used to disassemble the symbol information corresponding to an address and start part of the assembly implementation.

The following 0x600002f51110 is the address of the Block object. 16 is added because the internal offset of the Block object is the address of the function that executes the code stored in the Block object. So it is easy to know which Block object is holding the object and will not be released.

As you can see from the source code in the first figure above, the Block holds the self object internally, which prevents the object from being freed properly.

The above commands can be used anywhere to view the function information of a Block during debugging.

The caveat here is when you define multiple blocks within a method. The rule for the function notation of these blocks is:

-[Name of method where block is defined]_block_invoke. The serial numberCopy the code

The first block defined in a method has no ordinal number, and subsequent blocks are incremented from 2 by the number defined.

Such as the four blocks defined in the following class:

@interface CA
-(void)foo1{
      void(^b)(void) =^{};
      void(^b)(void) =^{};
}

-(void)foo2{
     void(^b)(void) =^{};
     void(^b)(void) =^{};
}
@end
Copy the code

The symbol for the corresponding block is:

-[CA foo1]_block_invoke
-[CA foo1]_block_invoke.2
-[CA foo2]_block_invoke
-[CA foo2]_block_invoke.2
Copy the code