📜 ⬆️ ⬇️

Xcode and advanced debugging in LLDB: Part 2

Good afternoon, today I offer you the second part of the article about debugging applications in LLDB.

In the first part, we figured out how to use breakpoints in Xcode to modify the existing properties of variables and add a line of code through instruction instructions.

I created a demo project intentionally with a few bugs in order to figure out how to use different types of breakpoints in LLDB to debug an application.
')
If you have not studied the first part of the article, better start with it. Let me remind you of the important rule of this tutorial: Until the end of this article, you do not stop the compiler and do not restart the application after the very first run. You correct errors during program execution.

Watchpoints

So, the following error in the application:

3. You can upload posts more than 7 times.

How to reproduce the error:


As one of the options for detecting errors, you need to find out how the integer pageNumber variable is updated after new posts are uploaded to the page. Since you are still not very familiar with my code, you have to spend some time to understand what is going on in it.

Do not worry. Let's apply some magic.

From the first part of the article, we learned that the GET HTTP request is performed in the pragma mark Networking section. It contains exactly one loadPosts function. Put a breakpoint on the first line of this function and pull the table down to update. The compiler will stop at this breakpoint.

image
Objective c

image
Swift

In the bottom window of the debugger, click on the "Show variables" button. On the left, a new window will pop up, in which you will see all the variables of PostsTableViewController.

image

Point the cursor to the pageNumber variable, right-click and select “Watch _pageNumber” / “Watch pageNumber” for Objective-C and Swift, respectively.

image
Objective c

image
Swift

Thus, you have created a so-called watchpoint for the pageNumber variable. A watchpoint is a breakpoint type that stops the debugger every time the value of the variable it is set to changes.

image
Objective c

image
Swift

Continue with the program. The debugger stops and you see something like the following:

Objective c

image

  1. Records of old and new values ​​of pageNumber variable.
  2. Tracking a stack of code that changes the value of the pageNumber variable.
  3. The current point that caused the change to the pageNumber variable is the setter method of this variable.

If you refer to item 1 in the stack tracking, it will lead you to the following code snippet:

image

Swift

image

  1. The debugger informs you that the observation point you have set has revealed something.
  2. Tracking a stack of code that changes the value of the pageNumber variable.
  3. The current point that caused the change to the pageNumber variable is the updateForNetworkCallEnd function.

It is logical to conclude that every time after a successful HTTP GET request, the pageNumber variable is incremented by 1 as long as the state variable (such as enum) is in the “active” state. This variable can have 2 states: either active (“active”) or inactive (“inactive”). The state “active” implies that the user can upload posts (that is, the limit of 7 downloads is not reached). The “inactive” state, on the contrary, implies that the user will no longer be able to load posts. As a result, we need to add logic to the updateForNetworkCallEnd function, which checks the pageNumber variable and sets the state to the corresponding state.

As you may have guessed, it is much easier to first test the hypothesis without stopping the compiler before making changes to the code.

I note that in the pragma mark Support section, we already have the function we need ( setToInactiveState ), which sets the state variable to “inactive”.
Add a breakpoint one line above the if condition. Also add the following instruction command to the debugger.

Objective c

expression if (self.pageNumber >= 7) {[self setToInactiveState]} 

image

Swift

 expression if (self.pageNumber >= 7) {setToInactiveState()} 


image

After that, delete the very first breakpoint you used to set the watchpoint. Also deactivate the watchpoint itself.

image
Objective c

image
Objective c

image
Swift

image
Swift

Now scroll up the tables, pull down to refresh and start flipping.
Everything worked out! But it is too early to celebrate, we still have one bug to fix!

What's next?

The final, third part of the article, in which we will learn about another type of breakpoint - symbolic breakpoints.

Source: https://habr.com/ru/post/432122/


All Articles