What's the difference between "p" and "po" in Xcode's LLDB debugger?
Asked Answered
S

10

21

Example: I write the following string in my old project and a new, clear one:

UIInterfaceOrientation k = [UIApplication sharedApplication].statusBarOrientation;

Console input/output for a clear project:

(lldb) po k
UIInterfaceOrientationLandscapeLeft

And something awful in my old project if I write "po k" - a list of useless integers.

Additionally, I can't print most of the objects in the new project.

Solarism answered 2/3, 2015 at 9:33 Comment(0)
S
-2
Strip debug symbols during copy

In most answers they advice to set optimization to "none" but forget that this option should be set to NO (at least for debug configuration).

Solarism answered 2/3, 2015 at 12:22 Comment(0)
M
40

I don't know what is going on in your case, but just so folks are clear on the difference between po & p:

The p command (a.k.a. expr --) takes the arguments it is given, compiles them as though they were a source code expression written in the context of the current frame, executes the result - either by running an interpreter on the result of the compilation if that is possible, or by JITing the result of the compilation, inserting it into the target program, and running it there. Then it prints the result of the evaluation.

The po command (a.k.a. expr --O --) does everything that p does, but instead of printing the result, if the result is a pointer to an ObjC object, it calls that object's "description" method, and prints the string returned by that method(*). Similarly, if the result is a CF object, it will call CFShow and print the result of that. If both these attempts fail, it will go ahead and print the result as p would have.

So po is mostly like p. But you can get some weird results if you use po on things that it aren't actually objects. For instance, ObjC has a optimization (tagged pointers) that represent the contents of some objects (e.g. NSNumbers) in the object pointer. There isn't a "real" object, just a cooked pointer. So if you try to po an integer that just happens to look like a tagged pointer, you'll get the description of some probably unrelated ObjC object, not the value of the integer.

And of course, po is doing a lot more work, so unless you really want some object's description of itself, p is more efficient.

  • Actually, it calls debugDescription, if that exists, and falls back to description if it doesn't...
Mckinzie answered 3/3, 2015 at 21:4 Comment(2)
Is po equivalent to expr -O -- (single dash vs double dash)?Ret
The po command is added to the built-in command set in lldb using: "command alias po expr -O --". If you run help po the last line in the output is: "'po' is an abbreviation for 'expression -O --'. The -- indicates the end of the command options, so all your input on the line is your expression. BTW you will get that same info for any alias command, of which there are a bunch pre-canned in lldb. If you are interested, issue the help command with no arguments and it will list first the built-in commands, then the aliases, then user-defined commands.Mckinzie
D
28

p = print

po = print object

p prints value of primitive variable or value of a reference

po try to call -description for that object and print returned string

Decoder answered 7/6, 2017 at 7:51 Comment(1)
This is not the whole picture. p prints a representation of the variable using lldb's data formatters. So for instance, though the actual value of an NSArray just has an isa field and no apparent data, lldb's data formatters know how to find the actual array contents and render them, and will do so. If you REALLY want to see the raw view of a variable, use expr --raw --.Mckinzie
I
12
  • Use po, p, & v to print variables

    • po ends up compiling & executing twice, once to evaluate your expression and again to get the object description.

    • v doesn’t compile at all: can’t evaluate any expression but does allow property accessing and does recursive dynamic type resolution so each property is treated as the actual runtime type.


enter image description here

For people who are interested in learning more : https://developer.apple.com/videos/play/wwdc2019/429/

Add this as an answer for visibility, Also explains the functionality of each debugging commmand

Incorporable answered 4/2, 2020 at 19:39 Comment(0)
T
5

po tries to treat what you want to print, as an object. In many cases it is similar to p, but there are cases where the difference emerges.

The simplest way to see the difference: compare the output of p 0 and po 0.

(lldb) p 0
  (int) $26 = 0
(lldb) po 0
  <nil>
Tribade answered 19/4, 2020 at 6:24 Comment(0)
S
1
p prints value of primitive variable or value of a reference
po try to call -description for that object and print returned string

There is also **v command** in lldb. Explaining using example.

protocol Activity {} 
struct Trip: Activity { 
var name: String 
var destinations: [String] 
} 
let cruise: Activity = Trip(...)

Using v command 
(lldb) v cruise.name
(string) cruise.name = "print name"
//As it uses dynamic resolution

Using p command
(lldb) p cruise.name
//execution interrupted
Sebbie answered 14/6, 2019 at 5:3 Comment(0)
S
1
  • Xcode's LLDB
    • p = print
      • is just alias for expression --
        • == expr --
      • internal
        • use lldb formatters
    • po = print object
      • is just alias for expression -O --
        • == expression --object-description --
          • -O == --object-description
        • == expr -O --
      • internal
        • if debugDescription exists
          • call -[curVar debugDescription]
        • if debugDescription not exists, fallbackto
          • call -[curVar description]
Splendent answered 12/4, 2023 at 6:39 Comment(0)
R
0

UIInterfaceOrientation is no (Objective-C) object, but an integer (enum:NSInteger). You should not use po (print object) at all.

Reproduce answered 2/3, 2015 at 11:45 Comment(2)
Yes, you should use that.Reproduce
In my case both of them work or not but always simultaneouslySolarism
S
0

It seems the difference is lldb/gdb debugger. The only way for iOS project to make debugger more workable is expr @import UIKit. But it may not work for older xcode versions and... you need to input this string in the console after each relaunch. The only way to automate it is an extra breakpoint with this expression.

Solarism answered 14/9, 2015 at 7:58 Comment(0)
S
-2
Strip debug symbols during copy

In most answers they advice to set optimization to "none" but forget that this option should be set to NO (at least for debug configuration).

Solarism answered 2/3, 2015 at 12:22 Comment(0)
A
-2

This is in reference to what Jim Ingham said. Type "p " instead of "po ". When I do that Xcode displays the correct information. Try that.

Altimeter answered 13/9, 2015 at 20:22 Comment(1)
facepalm, I have already wrote that both p and po display incorrect informationSolarism

© 2022 - 2024 — McMap. All rights reserved.