Xcode调试器(lldb)从内存地址获取对象描述

14

鲜为人知的事实是:在Xcode中,当使用调试器暂停时,现在可以自省通知中心以了解哪些对象注册接收哪些通知:

(lldb) po NotificationCenter.default

<NSNotificationCenter:0x6040000d40b0>
Name, Object, Observer, Options
com.apple.accessibility.reduce.motion.status, 0x10b126190, 0x7fc795700140, 1001
com.apple.accessibility.asst.scanner.status, 0x10b126190, 0x7fc795700140, 1001
// ... etc. ...

很好,但是我如何从获取内存地址0x7fc795700140到了解那是什么对象呢?

编辑:我会保留这个问题,但我认为正确的答案是在LLDB(Swift):将原始地址转换为可用类型中所示的类型。


我认为我在使用 po <address> as NSObject 时很幸运,首先得到了对象,然后尝试作为本地类型(但据我回忆,两者是相同的)。 - Chris Conover
3个回答

23

菲利普回答的Swift版本为:

(lldb) expr -l objc -O -- 0x7fc795700140
<UIApplication: 0x7fc795700140>

3
嗨 - 很好,但是请问我该如何获取一个值,以便可以向其发送方法呢? - Benjohn
@Benjohn 嗯,想必您认识这个对象并知道如何引用它。 - matt
1
@AlexZavatone 对不起,我还不信服。不过你可以自己回答! - matt
这是我使用的Swift等效命令:expr -l swift -O -- 0x7fc795700140。你提供的确切文本只适用于Objective-C对象实例,所以我有些困惑,你说“Swift等效命令是”,然后使用LLDB expr命令搜索Objective-C对象。我对这两种方法进行了严格测试,追踪了1400多个内存泄漏。无论如何,感谢你的帮助。 - Alex Zavatone
FYI,(e -l 在其他情境下也很有用。e -l Swift 允许您在堆栈帧为 Objective-C 时运行 Swift 代码。) - Alex Zavatone
显示剩余2条评论

10

po命令可用于地址(至少在Objective-C/Mac环境中)

例如:

(lldb) po [NSNotificationCenter defaultCenter]

NSWindowDidResizeNotification,0x7fff9a0e98e0,0x6100001246a0,1400

(lldb) po 0x6100001246a0

ExpandOneView:0x6100001246a0


1
嗨,菲利普!哎呀,(lldb) po 0x7fc795700140 OMM 的结果是 140495182364992。可能是因为这既不是 Objective-C 也不是 Mac OS。 - matt
3
好的,我知道怎么做:expr -l objc -O -- 0x7fc795700140 给出了你得到的结果。 - matt
5
也许相关的背景是:记住 po 只是 expr -O -- 的别名。它的作用是在给定(或当前帧的)语言中评估 -- 后面的表达式,然后调用其“适当的语言描述方法”。在 ObjC 的情况下,lldb 还会在发送描述消息之前将表达式的结果隐式转换为 id。Swift 没有这种基本对象类型,因此我们没有好的方法可以在我们只知道一个 Int 的情况下调用它的描述,所以我们不能对 Swift 使用同样的技巧。 - Jim Ingham

8

首先,我使用的是LLDB命令。

(lldb) expr -l objc -O -- 0x600001582d00

<__NSArrayI 0x600001582d00>(
<UIStoryboardShowSegueTemplate: 0x600002c3e4c0>,
<UIStoryboardPresentationSegueTemplate: 0x600001582210>,
<UIStoryboardPresentationSegueTemplate: 0x600001582620>,
<UIStoryboardShowSegueTemplate: 0x600002c3f4c0>,
<UIStoryboardPresentationSegueTemplate: 0x6000015839d0>,
<UIStoryboardShowSegueTemplate: 0x600002c3d680>,
<UIStoryboardEmbedSegueTemplate: 0x600002c3dc40>
)

对于一个 Swift 类的实例。

expr -l swift -O -- 

对于一个 Objective-C 类的实例。

expr -l objc -O --

对于一个 C++ 类的实例。

expr -l c -O --

现在,让我来解释一下。我有幸修复了我们初级iOS开发人员代码中超过1400个内存泄漏的问题。通常,在内存图调试器中检查泄漏对象时,我所拥有的仅仅是对象在内存中的地址。这是在Objective-C和Swift应用程序中进行的,因此我们必须能够检查来自两种语言的对象。当我在LLDB中进行操作时,我必须指定要检查的内存地址变量所属的语言。这适用于Swift、Objective-C和C语言。上面提供的是Swift、Objective-C和C语言的命令样例和示例输出。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接