LLDB is a debugging tool that comes with Xcode. If you use this debugging tool well during the development process, it is not only an improvement of your ability, but also a magic tool to install force.

How to enter THE LLDB

When a program crashes or has a breakpoint, it automatically changes to LLDB mode. You can also do this manually by clicking here:

2. Use LLDB

2.1 expr instruction

This instruction is meant to execute code logic in real time. Something like this:

When you click Next, NSLog prints CoderHG instead of Coder. This feature feels pretty good when you think about it.

2.2 the call

This instruction, similar to expr, invokes a line of code that looks like this:

call self.view.backgroundColor = [UIColor redColor];

2.3 print

In fact, about printing, should all small partners know. Following the above steps, do the following:

There are two common print instructions p and Po in LLDB.

  • 1. P is usually used to print values for basic data types. By default, this command produces a temporary variable, such as **$1**, which should be exciting to anyone who has studied the Shell.
  • 2. Po prints the contents of a variable. In the case of an object, the printed contents are determined by -debugDescription.

2.4 Operating Memory

Operations on memory are nothing more than read and write operations. Modify the value in memory:

Memory Write Memory address value

Example: Memory write 0x7FFEE685dba8 25

Read memory operation:

Memory Read/Quantity _ Format _ Number of bytes Memory address

or

X/Quantity _ Format _ Number of bytes Memory address

Against 2.4.1 format
  • X: indicates hexadecimal system
  • F: floating point number
  • D: indicates base 10
2.4.2 Byte size
  • B: Byte indicates one byte
  • H: Half word means 2 bytes
  • W: Word stands for four bytes
  • G: Giant word stands for eight bytes

Such as:

memory read/1wx 0x7ffee14a5ba8 memory read/1wd 0x7ffee14a5ba8

Read 4 bytes of 0x7FFEE14a5ba8. The following is an example:

2.5 bt

Bt returns all call stacks, as follows:

(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = step over
  * frame # 0: 0x000000010758b6fd LLDBDev`-[ViewController viewDidLoad](self=0x00007fedad7057e0, _cmd="viewDidLoad") at ViewController.m:27I killed a lot of them in the middle. ** frame#34: 0x000000010758b79f LLDBDev`main(argc=1, argv=0x00007ffee8674108) at main.m:14
    frame #35: 0x000000010c2d1d81 libdyld.dylib`start + 1
    frame #36: 0x000000010c2d1d81 libdyld.dylib`start + 1
Copy the code

This directive is so powerful that the current Xcode doesn’t even show up here:

So we have to use BT instructions.

Third, in actual combat

No actual combat armchair strategist, are playing hooligan. To begin, define a Class as follows:

#import <Foundation/Foundation.h>

@interface HGObject : NSObject

/ * * * / age
@property (nonatomic.assign) NSInteger age;
/ * * * / tall
@property (nonatomic.assign) NSInteger height;

@end



#import "HGObject.h"

@implementation HGObject

@end
Copy the code

Very simple Class.

3.1 Viewing the ISA Pointer of an object

It is said that the value of isa in an instance is the value of the class of the current instance. Start with a simple piece of code:

Class cls = NSClassFromString(@"HGObject");
id obj = [[cls alloc] init];
NSLog(@ % @, % @ "", cls, obj);
Copy the code

Run code to find:

  • 1. CLS does not display specific address values.
  • 2. Isa is not seen in obj at all.

You can’t see any address display, so you can only use LLDB debugging tools, even using simple P or Po instructions is not possible. Use the instructions above to manipulate memory.

The value of isa for instance of a Class object is the value of the Class object itself. Yes, that’s the way it is.

3.2 Viewing an Address in an Object

Simple implementation of the following code:

HGObject* obj = [[HGObject alloc] init];
obj.age = 18;
obj.height = 2;

NSLog(@"% @", obj);
Copy the code

Make a breakpoint at NSLog, run the code, and open the memory view:

This is what it looks like when it first opens:

Write the address of obj and look at the following image:

Looking at the memory map above, I noticed a pattern, as shown below:

The memory distribution in the figure above, shown in the red box, is ISA, _age, and _height. To verify this, modify the values and see what happens:

The logic in the figure above looks like this: find the address of _age and _height, change the address value, and then refresh to see the memory view.

Memory breakpoints

As the name implies, to a memory break point. In fact, in the development, or very practical, a bit like KVO listening. Here is a simple test code with a manual breakpoint in viewDidLoad to enter the LLDB environment:

Once in the LLDB environment, we can execute the following commands:

watchpoint set variable self->_name

The log is:

Watchpoint created: Watchpoint 1: addr = 0x7fcfaf9061d0 size = 8 state = enabled type = w
    watchpoint spec = 'self->_name'
    new value: 0x0000000000000000
Copy the code

The breakpoint is successful. Select * from memory where id = ‘_name’;

Of course, the instruction to set memory breakpoints can also be like this:

watchpoint set expression &_name

Memory breakpoints are especially useful when analyzing data flows, such as when a variable is nil.

Five, UI control view

This function can be powerful, first look at a question:

This is actually a problem after we do automatic layout, the console will give you this prompt. If the interface is simple, it’s easy to troubleshoot. If the interface is complex, it’s hard to locate the problem. So how do you find the specific view? You can do it like this:

In this way, you can locate the UI on the interface in real time. The specific command is as follows:

(lldb) e id $hgView = (id)0x7fdfc66127f0
(lldb) e (void)[$hgView setBackgroundColor:[UIColor redColor]]
(lldb) e (void)[CATransaction flush]
Copy the code

Note: the command must be executed, otherwise it will not work in the LLDB state.

Dynamic injection of code logic

It is strange to see this subtitle, which means how to modify the logic of the code by modifying it while it is running. It’s a little convoluted, but let’s do a quick example.

6.1 a scene

There is the following code:

The yesOrNo attribute is used to set the value of yesOrNo to true when the code is already running and wants to run again. What would you do? In fact, the above introduction, using expR can be done, but there are more advanced can be. Create a breakpoint and double-click it to make it edit, as shown below.


Expression yesOrNo = true will save you from going to LLDB every time you run this breakpoint.


Such a break point, is not very high! ??

6.2 scenario 2

If you want to know when the value of an attribute changes, what should you do? Because a lot of times, a property change will happen in many places, so how to achieve uniform tracking? Here’s what I did many years ago: I overwrote the set method and then set a breakpoint in the set method. This is excellent, but also the most unsightly. Because after overwriting the set method, you need to delete it again, which is too damn tedious. Why not make a break point? Furthermore, what about tracking the change in system properties? Here’s a cool way to do it. Take the listener -[UILabel setText:] method as an example. The first step is to tease her:

Then dish her up like this:

-[UILabel setText:]

Then, to your surprise, nothing is done and the breakpoint is triggered:

rogue

I only want to listen for -[UILabel setText:] triggered in btn1. What should I do? In real development, the BTN1 approach might be complex. Directly give the final treatment scheme:

This is a familiar picture. Breakpoint set-one-shot true –name “-[UILabel setText:]” breakpoint set-one-shot true –name “-[UILabel setText:]” Will be automatically triggered to trace.

What exactly does this break point do? You can just imagine it.

Seven, section

A common fix cycle is to modify the code, compile it, re-run it, and hope for the best.

Familiarizing yourself with some common LLDB debugging techniques can save you a lot of debugging time in actual development.

Viii. Other excellent articles

2. Xcode debug LLDB