This article is organized from the previous slide show. It mainly talks about Xcode combined with lldb debugging command and objc runtime debugging skills.
I. definition of common macros
1、OPTIMIZE, debug and release determination
- Release compile time definition
When we want some code to run only in debug environment, we can use this macro to define discrimination
2、i386Andx86_64, simulator environment determination
- Simulator compile time definition
Sometimes the Lib library relied on by the project only compiles the code of the real machine, and the simulator compiles in error. Use this macro to skip code that cannot be compiled for simulator debugging
3. Judgment of compiling SDK
- The SDK will declare the current SDK version definition and keep the previous SDK version definition
- Sometimes the code we write may not be compiled in the latest SDK, and there will be potential problems in the compilation of the old SDK. Use this decision to write code respectively for the new and old SDK versions
__IPhone > OS > version > Max > allowed. This macro definition declares the currently compiled SDK version and can be compared
4. Use the – D compiler option to add macro definitions for compiling target
- Defined in other C flags project of project target
- Due to different certificates, channels and UI, multiple targets will be created for the same code to be packaged separately. By appending macro definitions at compile time, target can be determined at run time.
- The following example defines a macro xdtarget with a value of 800100.
Each target can define different values for xdtarget, so that the runtime can identify the target and avoid the trouble of manual modification.
- In C languagenop() function, representing an empty statement. Not available in OC.
You can design a macro to replace it, which is used to mount conditional breakpoint debugging.
II. Common debugging commands
1. Po, output object information
- Po calls the description method of nsobject to print the object
- Po variable name
- Po memory address
- Po returns the expression of an object
- If the object is not released, the Po will output content, otherwise only a number representing the wild pointer will be output. According to this feature, you can determine whether the object is released normally in the circular reference check.
- Complex query with expression
2. P, output variable value
- P (type) expression
In addition to value types, you can also print structure data directly
3. Call, execute a piece of code
- Call (return type) expression
In debugging state, support for point syntax is poor. If a symbol is not found, try sending a message. If not, declare the type as prompted. It is also necessary to pay attention to Po, P and other instructions
Values can be modified.
- Under GDB, set can be used, but under lldb, set syntax meaning has changed, and call is used instead of set instruction
CoordinationNOPAnd breakpoints, which can dynamically control the running state of the program at runtime
Can execute a piece of code
4. BT, print call stack
3. Tips for using breakpoints
1. What can a breakpoint do?
- You can add a condition that triggers a breakpoint when it is met.
- Or it will be triggered after some times of execution
Several kinds of actions can be performed
When this breakpoint is passed, the action is executed but the program is not interrupted
2. Abnormal breakpoint
Some crashes are caused by exceptions thrown by the program, such as array overruns. You can monitor where an exception is thrown by adding an exception breakpoint.
3. Symbol breakpoint
- When the method corresponding to the symbol is called, the
- -/+[class method]
For example, when uiviewcontroller is loaded, it will trigger and output the current call stack
4. Memory breakpoint
- Interrupt when the block memory is called
The Xcode debugging interface can simplify the addition of instructions
When adding, you need to interrupt in advance to find the memory address to be monitored (note that the address will fail every time it is started)
It can output the change of value. You can find out when memory was modified and how values changed.
IV. flexible use of debugging means
Although the above debugging methods seem simple, they can bring a lot of convenience and possibility for debugging as long as they are used flexibly.
For example, here’s an example
There are three variables a, B, C. As long as a conditional breakpoint is added to the NOP statement to execute the call command, by adjusting the opening and closing of the breakpoint, the value of a, B, C can be dynamically controlled when the program is running. This makes it possible to simulate various states and dynamically debug program branches without writing debugging code.
In addition, when an exception occurs to the program, the error message is usually reported through the console to passively locate the problem. If you use the debugging command in combination with the objc runtime, you can actively know the abnormal state. In the era of MRC development, for the problem of releasing objects many times, we can even restore the zombie objects back to the original objects to a certain extent, so as to locate the problem.
So as long as you use these debugging methods flexibly, I believe you will soon become a debugging expert.