【问题标题】:Why aren't mutating members triggering breakpoints in Xcode?为什么变异成员不触发 Xcode 中的断点?
【发布时间】:2018-04-19 18:58:53
【问题描述】:

我遇到了一些我似乎无法通过阅读 Xcode 或 LLDB 的文档来解决的问题。当应用程序到达具有断点的行时,在我看来,如果存在断点,LLDB 应该在该行中断。如果在执行变异函数时访问该行上的代码不会触发断点。

考虑以下示例:

class DataSource {

    private init(){

        data = []

        for i in 0..<10 {

            data.append(i) // mutating func
        }
    }

    static let sharedInstance = DataSource()

    var data: [Int]! // Set a breakpoint on this line
}

class Worker {

    func work(){

        print("Append item")

        DataSource.sharedInstance.data.append(23) // mutating func

        print("Get first item")

        print(DataSource.sharedInstance.data[0]) // subscript - TRIGGERS BREAKPOINT

        print("Drop first")

        print(DataSource.sharedInstance.data.dropFirst()) // func - TRIGGERS BREAKPOINT

        print("Remove first")

        print(DataSource.sharedInstance.data.removeFirst()) // mutating func

        print("Remove at 0")

        print(DataSource.sharedInstance.data.remove(at: 0)) // mutating func
    }
}

.data[0].dropFirst() 正在触发断点,其他函数调用没有。我能看到的唯一区别是那些没有破坏的函数是mutating函数。

虽然没有触发断点,但每次都会触发在同一行添加的观察点。

有人可以解释一下这种行为吗?

【问题讨论】:

    标签: ios swift xcode debugging lldb


    【解决方案1】:

    在 macOS 上,您的断点解析为:

    (lldb) break list
    Current breakpoints:
    1: source regex = "Set a breakpoint", exact_match = 0, locations = 3, resolved = 3, hit count = 3
      1.1: where = mutable`mutable.DataSource.(in _788A7EC739C0395377AC3966BEDD9D35).init() -> mutable.DataSource + 40 at mutable.swift:15, address = 0x0000000100001b08, resolved, hit count = 1 
      1.2: where = mutable`mutable.DataSource.data.getter : Swift.ImplicitlyUnwrappedOptional<Swift.Array<Swift.Int>> + 80 at mutable.swift:15, address = 0x0000000100001e00, resolved, hit count = 2 
      1.3: where = mutable`mutable.DataSource.data.setter : Swift.ImplicitlyUnwrappedOptional<Swift.Array<Swift.Int>> + 96 at mutable.swift:15, address = 0x0000000100001e70, resolved, hit count = 0 
    

    这是有道理的,“数据”ivar 的定义产生了一个 setter、getter 和 init 方法,并且这些函数与这一行相关联。

    但是,如果您查看可变访问的代码,例如 append 调用,则没有使用这些方法,而是程序集如下所示:

    (lldb) dis -c 5 -s 0x10000203b
    mutable`Worker.work():
        0x10000203b <+235>: callq  0x100002cf0               ; type metadata accessor for mutable.DataSource at mutable.swift
        0x100002040 <+240>: movq   %rax, -0xf0(%rbp)
        0x100002047 <+247>: callq  0x100001d50               ; mutable.DataSource.sharedInstance.unsafeMutableAddressor : mutable.DataSource at mutable.swift
        0x10000204c <+252>: movq   (%rax), %rax
        0x10000204f <+255>: movq   %rax, %rcx
    

    它通过类型元数据来访问它要改变的变量。这是一个通用函数,不会由“数据”ivar 的定义触发,因此它不会分配给该定义行。该访问必须知道它可以跳过 getter 或 setter,但您必须让其他人解释它为什么这样做......

    如果您对此感到好奇,可以尝试将您的问题重新表述为关于 Swift 为数据访问所做的选择,并且更熟悉该语言的实现的人可能会参与进来。

    【讨论】:

      猜你喜欢
      • 2012-04-27
      • 2012-09-10
      • 1970-01-01
      • 2010-09-09
      • 2011-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多