1

I'm facing big issues when trying to print out Objective C properties in many situations when I'm almost certainly sure it SHOULD work.

Consider the following setup:

Case setup

The view controller's property has strictly set class (Card *), but still, LLDB outputs an parsing error where subproperty cannot be found on object of type id.

Having an object property defined on a view controller (see points 5 & 6):

  1. stop at breakpoint inside the controller code (f.e. in -viewDidAppear: method)
  2. try to print out the property itself with po _card (points 1 & 2)
  3. try to print out its subproperty with po _card.offlineURL (points 3 & 4)
  4. an LLDB parsing error occurs

Printing out via [_card offlineURL] prints out proper object description as LLDB sends a message to Card object with no class check.

Definition of object property on the controller declares non-id class, though (point 5).

I'm expecting LLDB to print out the property object's subproperty description, NSString containing URL string in this case, but this annoying LLDB error occurs instead.

This is just a single example from many. Sometimes it affects direct property printout, numbers printing etc. These issues are way more frequent since integration of Swift began, being worse with every new version of Xcode since 6.2, including the latest 7.2.

This happens in my Objective C project in many situations, though sometimes it works fine in different cases.

Do you know about any work-arounds or fixes for this issue? I've already filed a report on Apple Bug Reporter, but this will certainly take time for Apple to even notice.

asked Jan 4, 2016 at 10:41
4
  • Try this command in the debugger, and then try again: e @import UIKit. Commented Jan 4, 2016 at 10:49
  • No difference unfortunately. Importing UIKit module would probably have no effect as this is most probably caused by LLDB itself and its way of parsing commands (maybe broken to force me migrate to Swift? Thank you, Apple) – its not related to a UIViewController stuff, if I'd have a hierarchy of objects and want to print its sub-sub-sub-properties, it would fail the same way (and it happens, f.e. in singleton managers not working with any UIKit stuff, just pure Foundation code), this specific example is only another I've just found. Commented Jan 4, 2016 at 10:56
  • I've faced the same issue, and just the other day I learned of the @import trick. I don't know why it seems to work on non-UI classes, but for me it does. Sorry it didn't help you. Commented Jan 4, 2016 at 11:02
  • Importing UIKit will make all the types from UIKit (and the modules it depends on) available, even if there isn't debug info for them. But the type that isn't printing for michi is presumably one of his own types, and not from UIKit. So that wouldn't help. Commented Jan 4, 2016 at 23:17

1 Answer 1

1

The most likely problem given the info in your question is that we don't actually have debug information for _card.

The lldb command:

(lldb) image lookup -t Card

will tell you whether lldb had debug information for Card available to it. If this doesn't find anything, then maybe some part of your project isn't getting built with debug info. If the command does find some correct definition of Card, then it must be that the debug info for the _card ivar is not getting hooked up to this type correctly.

If there is a definition of Card, then the workaround:

(lldb) po ((Card *) _card).offLineURL

is available.

For future reference, there are two other bits of behavior that are probably complicating your attempt to figure out what is going on here:

1) (w.r.t. picture 3) The Xcode IDE uses its built-in indexer for auto completion in the debug window as well as the Source Code editor. But the debugger runs off debug information, since we need to be able to debug things that aren't built in Xcode. So the fact that auto-completion can find a name in an expression doesn't tell you anything about what lldb will do.

2) (w.r.t. picture 2) po force-casts the expression you are trying to "po" to an ObjC object (i.e. "id") and then calls its description method. The description method of an ObjC object that doesn't override description prints the type name and the address. So lldb didn't need to know the type of the _card ivar to get the output you saw. We only start to need types when the expression is more complex and involves accesses to ivars or properties of an ObjC object in the expression.

Note also, by default if you do:

(lldb) print _card

lldb will evaluate the expression "_card", find it resolves to a pointer of at least type id, then follow that pointer's isa pointer into the ObjC runtime to figure out what the dynamic type is. So it is likely to print Card * in this case.

But the expression parser hasn't yet been taught to resolve the dynamic type of sub-expressions within the expression parser in mid-parse. That would actually be quite a trick... So if it doesn't know the full type of _card, then:

(lldb) print _card.offlineURL

isn't going to work, since id does indeed not have a property of that name.

You can work around this by doing:

(lldb) print _card
0ドル = (Card *) 0x12345678

Then:

(lldb) print 0ドル.offlineURL

since the result variable captures the full dynamic type information, that will also be available in subsequent expressions.

answered Jan 5, 2016 at 1:54
Sign up to request clarification or add additional context in comments.

7 Comments

Yeah, you have good points, but I still feel there's something very wrong in the way LLDB evaluates it at this time. image lookup command shows me proper info about declaration in a header file along with all the properties listed. Casting a property is quite obvious, but very annoying when you need to fast-watch variables or method results quickly, which you usually need when debugging.
Another set of dizzy behaviour: po [SessionManager defaultSession] prints out proper description of a singleton object, calling po [SessionManager defaultSession].userInfo throws no known method '+defaultSession'; cast the message send to the method's return type – how cannot it find the method, when it's been called on the previous line with no issues? Trickily, po @(124).integerValue or po @"Hello World!".length works with no issues, though I don't find it in any way less complicated than evaluating over own classes above.
Even simple p self.view.frame ends with property 'frame' not found on object of type 'UIView *' – that's totally awkward. On the other hand, p _card.offlineURL prints proper variable value, what's the difference in parsing in po then? I would somehow bet NSString * has its -description implemented.
For [SessionManager defaultSession] all the expression parser needs to know is that the result of the expression has type "id". Actually it doesn't even need to know that, we just assume it is and try to send it the description message. However, to get the property userInfo from the result of [SessionManager defaultSession] we actually need to know the type retuned by the defaultSession message. We don't have debug info for that, so we query the runtime, but sadly all it records is that this method returns an id. So we have no idea whether that property exists, or what it is.
You might think the debugger should just go ahead and try the property access even if it has no idea what the property type is. That would certainly reduce the amount of type info we needed. Sadly, for most modern ABI's if you are returning a struct type, the caller allocates space for it on the stack, and the callee writes into that memory. So if we think something returns a scalar but it doesn't, calling the function silently corrupts the program stack. We try hard not to do that...
|

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.