ios - 我如何在 iOS 中读取 ptr_refs 给出的引用?

标签 ios objective-c swift xcode lldb

当使用 ptr_refs 打印引用列表时,它会给出一些模糊的结果(至少在 iOS 中)。例如,我有一个示例应用程序,其中包含这个微小的 ViewController 类以及对 UILabel 实例的一个导出引用:

import UIKit

class ViewController: UIViewController {

    @IBOutlet var label: UILabel!

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        print(label)
    }

}

这是我在打印标签引用时得到的列表:

(lldb) ptr_refs 0x102914810
0x0000000281b04630: malloc(    16) -> 0x281b04630
0x0000000283d09f18: malloc(    96) -> 0x283d09ec0 + 88    
0x0000000280c18d60: malloc(    64) -> 0x280c18d40 + 32     CFXNotificationNameWildcardObjectRegistration0 bytes after CFXNotificationNameWildcardObjectRegistration
0x000000028192b408: malloc(    32) -> 0x28192b400 + 8      _UILabelStringContent._UILabelContent._defaultAttributesProvider
0x0000000283a3d2f0: malloc(    80) -> 0x283a3d2c0 + 48     CFXNotificationObjcObserverRegistration8 bytes after CFXNotificationObjcObserverRegistration
0x0000000283a3d2f8: malloc(    80) -> 0x283a3d2c0 + 56     CFXNotificationObjcObserverRegistration16 bytes after CFXNotificationObjcObserverRegistration
0x000000010290c070: malloc(   864) -> 0x10290bd20 + 848    TtC13ThreadChecker14ViewController216 bytes after TtC13ThreadChecker14ViewController
0x0000000102d058c0: malloc(   304) -> 0x102d05850 + 112

如果这不仅仅是一个示例应用程序,而且它有 10-15 个 socket 引用,那么我将很难找出代码中这一行的确切引用 - 0x000000010290c070: malloc( 864 ) -> 0x10290bd20 + 848 TtC13ThreadChecker14ViewController216 字节后 TtC13ThreadChecker14ViewControllerThe

我还尝试了启用 MallocStackLogging-s 选项,但是当涉及到 socket 引用时,此信息不是很有帮助。

如果我只有一个对象的地址ptr_refs给出的列表,有没有办法找出我的中的确切变量/字段代码与 list 中的引用相对应?

最佳答案

首先,右侧的名称给了我们一些线索,从中您可以猜测 TtC13ThreadChecker14ViewController 与您的 ViewController 类关联。

_Tt 为目标; C 代表类别; 13是“ThreadChecker”字符串的长度,你的项目名称是ThreadChecker; 14 是“ViewController”字符串的长度,即类。你的ViewController从0x10290bd20开始。

其次,malloc 位于 0x000000010290c070。请注意,0x000000010290c070 - 0x10290bd20 = 0x350(十进制为 848),这就是为什么它将距“ViewController”开头的偏移量设置为 848,即 0x10290bd20 + 848。因此,这个偏移量 848 是拼图中的一个重要部分。

第三,接下来要做的就是找出源代码中的哪一行位于偏移量 848 处。为此,我们首先要做

(lldb) image list
[  0] 4EB96CD6-42E0-34D8-AB5B-2418F5C55678 0x000000010252c000 /Users/daniel.wong/Library/Developer/Xcode/DerivedData/testLLDB-eqmuowhdphumqdhcyvcydgrybiue/Build/Products/Debug-iphonesimulator/testLLDB.app/testLLDB 

即使在这个简单的示例中,应用程序也可能加载 200-300 个库。对于当前对您自己的源代码的调查,您可以忽略库,只查看 [0](列表中的第一个元素)。 (在我的示例中,该应用程序称为 testLLDB;在您的示例中,您可能会看到 ThreadChecker 而不是 testLLDB)。

需要注意的重要一点是,图像列表提供了所谓的文件地址,其中您从 Xcode 获取的用于 ptr_refs 的地址可能会完全不同(实际运行期间模拟器或 iPhone 内存中的实际地址(当它加载到 RAM 的一部分时),例如,示例中的 0x102914810文件地址指的是每个目标文件定义的虚拟地址。为了找到偏移量为 848 的源代码行号,您可以使用这些文件地址,现在只需要多一条信息,即 ViewController 代码的开始位置在哪里,这样您就可以获取偏移量848 从那里。

第四,要找到ViewController代码的开头,您可以使用

(lldb) image dump sections  /Users/daniel.wong/Library/Developer/Xcode/DerivedData/testLLDB-eqmuowhdphumqdhcyvcydgrybiue/Build/Products/Debug-iphonesimulator/testLLDB.app/testLLDB

我们仅指定了我们获得的 testLLDB 应用程序的图像作为图像列表的第一个元素,而不是之后的数百个库。

lldb 会给你类似的东西:

Sections for '/Users/daniel.wong/Library/Developer/Xcode/DerivedData/testLLDB-eqmuowhdphumqdhcyvcydgrybiue/Build/Products/Debug-iphonesimulator/testLLDB.app/testLLDB' (x86_64):
  SectID     Type             Load Address                             Perm File Off.  File Size  Flags      Section Name
  ---------- ---------------- ---------------------------------------  ---- ---------- ---------- ---------- ----------------------------
  0x00000100 container        [0x0000000000000000-0x0000000100000000)* ---  0x00000000 0x00000000 0x00000000 testLLDB.__PAGEZERO
  0x00000200 container        [0x000000010252c000-0x0000000102532000)  r-x  0x00000000 0x00006000 0x00000000 testLLDB.__TEXT
  0x00000001 code             [0x000000010252d260-0x000000010252fa80)  r-x  0x00001260 0x00002820 0x80000400 testLLDB.__TEXT.__text
  0x00000002 code             [0x000000010252fa80-0x000000010252fb5e)  r-x  0x00003a80 0x000000de 0x80000408 testLLDB.__TEXT.__stubs
  0x00000003 code             [0x000000010252fb60-0x000000010252fce2)  r-x  0x00003b60 0x00000182 0x80000400 testLLDB.__TEXT.__stub_helper
  0x00000004 data-cstr        [0x000000010252fce2-0x00000001025309bf)  r-x  0x00003ce2 0x00000cdd 0x00000002 testLLDB.__TEXT.__objc_methname
  0x00000005 data-cstr        [0x00000001025309c0-0x0000000102531817)  r-x  0x000049c0 0x00000e57 0x00000002 testLLDB.__TEXT.__cstring
  0x00000006 regular          [0x0000000102531820-0x0000000102531b50)  r-x  0x00005820 0x00000330 0x00000000 testLLDB.__TEXT.__const
...

还有更多,但是对于这个简单的 ViewController,前几部分足以满足我们的目的。查看第一个代码部分,其范围为 [0x000000010252d260-0x000000010252fa80)。所以它是从0x000000010252d260开始的。这里是我们添加偏移量 848 的地方。但是我们添加的是十六进制,因此我们将 0x350 添加到 0x000000010252d260 得到 0x000000010252d5b0

第五,也是最后,我们可以通过以下方式查看源代码的哪一部分引用了标签:

(lldb) image lookup -a 0x000000010252d5b0 --verbose
  Address: testLLDB[0x00000001000015b0] (testLLDB.__TEXT.__text + 848)
  Summary: testLLDB`key path getter for testLLDB.ViewController.label : Swift.Optional<__C.UILabel> : testLLDB.ViewController + 80 at <compiler-generated>
   Module: file = "/Users/daniel.wong/Library/Developer/Xcode/DerivedData/testLLDB-eqmuowhdphumqdhcyvcydgrybiue/Build/Products/Debug-iphonesimulator/testLLDB.app/testLLDB", arch = "x86_64"
  CompileUnit: id = {0x00000000}, file = "/Users/daniel.wong/OneDrive - V-Key Pte Ltd/ios/testLLDB/testLLDB/testLLDB/ViewController.swift", language = "swift"
 Function: id = {0x10000032e}, name = "key path getter for testLLDB.ViewController.label : Swift.Optional<__C.UILabel> : testLLDB.ViewController", mangled = "$s8testLLDB14ViewControllerC5labelSo7UILabelCSgvpACTK", range = [0x000000010252d560-0x000000010252d5bf)
 FuncType: id = {0x10000032e}, byte-size = 8, compiler_type = "() -> ()
"
   Blocks: id = {0x10000032e}, range = [0x10252d560-0x10252d5bf)
LineEntry: [0x000000010252d560-0x000000010252d5c0): /Users/daniel.wong/OneDrive - V-Key Pte Ltd/ios/testLLDB/testLLDB/<compiler-generated>
   Symbol: id = {0x000000a4}, range = [0x000000010252d560-0x000000010252d5c0), name="key path getter for testLLDB.ViewController.label : Swift.Optional<__C.UILabel> : testLLDB.ViewController", mangled="$s8testLLDB14ViewControllerC5labelSo7UILabelCSgvpACTK"
 Variable: id = {0x100000345}, name = "label", type = "testLLDB.ViewController", location = DW_OP_fbreg(-16), decl = ViewController.swift:18

所以我们看到它是 ViewController.swift:18 处的“testLLDB.ViewController.label 的关键路径 getter : Swift.Optional<__C.UILabel> : testLLDB.ViewController”,这就是您正在寻找的内容。 (好吧,对于我的测试 View Controller ,标签位于第 18 行,因为我也有一个 viewDidLoad 花了几行;对于你的,你应该为你的 ViewController 获取适当的行号)。

这篇文章已经太长了,但只是添加一点信息:那些来自 CFXNotificationObjcObserverRegistration 对标签的引用,这是 CoreFoundation 的一部分,所以我们看到引用不是来 self 们自己的源代码。许多引用文献通常来自 CoreFoundation 等系统框架;例如,如果您将带有标签的 View 放在 Storyboard 中并添加自动布局约束,则 ptr_refs 命令将另外为您提供许多与自动布局相关的其他引用,例如,

NSContentSizeLayoutConstraint.NSLayoutConstraint._container
0x000060000049ce48: malloc(    96) -> 0x60000049ce40 + 8      NSContentSizeLayoutConstraint.NSLayoutConstraint._container
0x00006000035db208: malloc(    64) -> 0x6000035db200 + 8      NSLayoutDimension.NSLayoutAnchor._referenceItem
0x00006000035db3c8: malloc(    64) -> 0x6000035db3c0 + 8      NSLayoutDimension.NSLayoutAnchor._referenceItem
0x00006000035e9560: malloc(    64) -> 0x6000035e9540 + 32 

关于ios - 我如何在 iOS 中读取 ptr_refs 给出的引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62310636/

相关文章:

ios - UIScrollView 没有滚动另一个 subview 的内容

ios - 为什么 AVPlayer 不会在 HLS 流视频的最后一帧停止?

ios - 更新 Xcode 后的 EXC_BAD_ACCESS (SIGABRT)

ios - 有什么方法可以连续为 Collection View 单元格调用 initialLayoutAttributesForAppearingItemAtIndexPath 并延迟一些?

Swift:从其他类访问变量

ios - iPhone真机自动化环境搭建

iphone - iOS 7 UItableview 单元格背景 View

ios - 自动布局 View 在不同的屏幕尺寸上总是相同的尺寸

ios - Swift - 已完成的 Game Center 成就

ios - 将数据从表传递到第一个 View Controller - 错误 : unexpectedly found nil while unwrapping an Optional value