同时访问 - 如何找出正在访问的内容?

时间:2018-06-08 13:57:02

标签: swift xcode

我的应用程序崩溃了这条消息:

  

同时访问0x7fa4a8e10d68,但修改需要独占访问。

如何找出0x7fa4a8e10d68对应的内容?当我尝试搜索它时,它不会出现,请参阅我附加的图像。 enter image description here

根据屏幕截图提供的内容,如何知道问题是gallaryModel还是galleries[indexPath.row]

1 个答案:

答案 0 :(得分:1)

1。简单案例

有几种方法可以对此进行调查。在简单的情况下,运行时错误消息可以为您提供足够的线索来弄清楚冲突是什么。例如,在您的情况下,错误消息会通知您当前访问权限是修改 –因此,在这样的行上:

galleryModel.requestNameUpdate(for: galleries[indexPath.row], with: resulting)

假设galleryModel是一种值类型,并且requestNameUpdate是一种mutating方法,则冲突必须与galleryModel相同,因为该行上的所有其他访问都将被读取。


2。查看以前的访问权限

在大多数情况下,您可以使用的另一个选项是查看以前的访问发生在哪里,这应该为您提供足够的信息以推断哪个变量发生冲突。为了演示,让我们考虑以下程序:

func bad(_ x: inout [String], _ body: () -> Void) {
  body()
}

var s = [String]()
var a = "hello"

do {
  bad(&s) {
    s.append(a) // Thread 1: Simultaneous accesses to 0x100556a50 [...]
  }
}

在Xcode中运行此命令将暂停上一行的执行:

enter image description here

如果我们单击堆栈跟踪中的“以前的访问(从此处开始进行修改)”(以红色突出显示),Xcode将向我们显示上一次访问的开始行:

enter image description here

在此示例中,有足够的信息可以知道变量s是冲突的变量。


3。检查变量地址

在更一般的情况下,您可以检查变量的内存地址以确定哪个冲突。继续上一个示例,我们可以右键单击变量查看器中显示的任何变量,然后通过选择“查看[...]的内存”来调出内存查看器:

enter image description here

这将为我们提供变量的地址(以红色突出显示)。如果此地址与错误消息中显示的地址相匹配(例如在这种情况下),则表明存在冲突。


4。拆卸

另一种选择是查看反汇编,以查看如果未发生冲突,我们将试图做的事情。我们可以在调试器中通过运行disassemble -a <address>并使用swift_beginAccess上方的堆栈帧的地址来完成此操作:

enter image description here

然后,您要导航到上面用红色突出显示的偏移量,在这种情况下为+ 174,它为我们提供了在调用swift_beginAccess之后的位置:

enter image description here

然后我们可以看到,如果不是因为冲突而调用Array的{​​{1}}方法(在append(_:)处),那是受保护的调用+ 193 / swift_beginAccess对。由此可以推断出冲突中的变量一定是swift_endAccess