我如何阅读 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
当使用 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