My question is related to “chapter 7: Image” about inspecting the block object’s members.
I found out that you mentioned 2 ways for this, either by:
querying for the object knowing the type by using the image command, e.x: (lldb) image lookup -t __block_literal_5
querying the object knowing the type and the memory address, and dereferencing it, using the p command, e.x: (lldb) p *(__block_literal_5 *)0x0000618000070200
Both are dumping kinda similar info, but I can’t exactly put my fingers on the exact difference between them.
So my questions are: 1) What exactly are the differences between the 2 ways mentioned above. 2) Why I can’t use image lookup -a 0x0000618000070200 to print the object details as the help image lookup states? 3) When I execute image lookup -t __block_literal_5, it dumps:
id = {0x100000c70}, name = "__block_literal_5" // and some more info too
what is the id? Shouldn’t it be the memory address of the __block_literal_5?
4) In section “Snooping around” of chapter 7, you mentioned that I have to increment the retainCount by using the -[__NSMallocBlock retain], otherwise the block will disappear when the references that are retaining this block release their control. So I tried to -[NSBlock invoke] and when I call -[__NSMallocBlock retainCount], it’s always 1. Is there any explanation for this? Why it never disappears?
Notes:
0x0000618000070200 is the address of the __block_literal_5
1). The image lookup -t __block_literal_5 method is consulting LLDB’s type system (which in turn is consulting the DWARF debugging info). When LLDB attaches to a process is has to go thread each and every module that’s loaded and parse any known data structures in the module’s symbol table (symbol tables are discussed a bit in the Mach-O chapters) and debugging info, if available.
The p *(__block_literal_5 *)0x0000618000070200 method is casting that address to the __block_literal_5 type, which is giving you the real life values of that block instance.
Another way of phrasing this is, one method is examining the members of a struct, the other is examining an instance of that struct.
You can find the implementation of Objective-C blocks here: Block_private.h
2). That address 0x0000618000070200 is an instance of the __block_literal_5 struct which is created on the heap (although not all Objective-C blocks are all created on the heap, some can be created on the stack). LLDB is not smart enough to figure this out since it’s an address that is created at runtime. That being said, it’s definitely possible to do some address sleuthing to try and determine what this address is via a custom LLDB script.
3). The id should not be interesting to you. It is used by the DWARF debugging to associate pointers to the correct types. When you pause in Xcode on a certain function, that function is consulting the debugging information provided by the compiler on the objects in that function as well as their types to give you information about what those references contain. DWARF debugging is a complex topic, there’s not really any need for you to know the details unless you are implementing your own parser for this information.
4). Looks like you found an error in the book. When I originally wrote that chapter, the block logic was a bit different. Now it looks like the retainCount is hardcoded to 1