我如何阅读 ptr_refs 在 iOS 中给出的参考文献?

How do i read references given by ptr_refs in iOS?

当使用 ptr_refs 打印参考列表时,它给出的结果有些模糊(至少在 iOS 中)。例如,我有一个示例应用程序,其中包含这个微小的 ViewController class 和一个 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 个插座引用,我将很难弄清楚此行在我的代码中的确切引用 - 0x000000010290c070: malloc( 864) -> 0x10290bd20 + 848 TtC13ThreadChecker14ViewController216 bytes after TtC13ThreadChecker14ViewControllerThe

我还尝试了启用 MallocStackLogging-s 选项,但是对于出口参考,此信息不是很有帮助。

如果我只有对象的地址ptr_refs给出的列表,有没有办法找出确切的variable/field 我的代码对应列表中的引用?

首先,右边的名字给了我们一些线索,从中你可以猜到TtC13ThreadChecker14ViewController与你的ViewController有关 class.

_Tt 为目标; C代表class; 13是“ThreadChecker”字符串的长度,你的项目名称是ThreadChecker; 14是“ViewController”字符串的长度,也就是class。您的 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 应用程序的图像作为 image list 的第一个元素,而不是之后的 100 个库。

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

所以我们看到它是 testLLDB.ViewController.label 的关键路径 getter : Swift.Optional<__C.UILabel> : testLLDB.ViewController 在 ViewController.swift :18,这就是您要找的。 (好的,对于 我的测试视图控制器 ,标签在第 18 行,因为我也有一个 viewDidLoad 需要几行;对于你的,你应该为你的ViewController).

这个 post 已经太长了,但只是想再添加一点信息:那些来自 CFXNotificationObjcObserverRegistration 对您的标签的引用,那是 CoreFoundation 的一部分,所以我们看到不是at 引用来自我们自己的源代码。许多参考资料通常来自 CoreFoundation 等系统框架;例如,如果您将带有标签的视图放入情节提要中并添加自动布局约束,则 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