Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simultaneous accesses -- how can I find out what is being accessed?

Tags:

xcode

swift

My app is crashing with this message:

Simultaneous accesses to 0x7fa4a8e10d68, but modification requires exclusive access.

How can I find out what 0x7fa4a8e10d68 corresponds to? It's not coming up when I try to search for it, see the image I attached. enter image description here

Based on what is provided is the screenshot, how would one know whether gallaryModel or galleries[indexPath.row] is the issue?

like image 528
Sami Avatar asked Jun 08 '18 13:06

Sami


1 Answers

1. Simple cases

There are a few ways you can go about investigating this. In simple cases, the runtime error message can give you enough of a clue to work out what the conflict is. For example, in your case the error message informs you that the current access is a modification – therefore on a line like this:

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

Assuming galleryModel is a value type, and requestNameUpdate is a mutating method, the conflict must be with galleryModel, as all other accesses on that line are reads.


2. Looking at the previous access

Another option you can use in most cases is to look at where the previous access occurred, which should give you enough information to deduce which variable is in conflict. To demonstrate, let's consider the following program:

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 [...]
  }
}

Running this in Xcode will pause the execution on the above line:

enter image description here

If we click on "previous access (a modification) started at" in the stack trace (highlighted in red), Xcode will show us the line where the previous access started:

enter image description here

And in this example, that's enough information to know that the variable s is the one in conflict.


3. Inspecting variable addresses

In more general cases, you can inspect the memory addresses of variables in order to determine which one is conflicting. Continuing from the previous example, we can right click on any of the shown variables in the variable viewer and bring up the memory viewer by selecting "View memory of [...]":

enter image description here

Which will give us the address of the variable (highlighted in red). If this address matches the one shown in the error message (such as in this case), we've found the conflict.


4. Disassembly

Another option is to view the disassembly to see what we would have been attempting to do if the conflict hadn't taken place. We can do this in the debugger by running disassemble -a <address> and using the address of the stack frame above swift_beginAccess:

enter image description here

You then want to navigate to the offset highlighted above in red, in this case + 174, which gives us the location after the call to swift_beginAccess:

enter image description here

We can then see that we would have been calling Array's append(_:) method (at + 193) if it hadn't been for the conflict, as that's the call being guarded by the swift_beginAccess/swift_endAccess pair. From that we can deduce that the variable in conflict must have been s.

like image 51
Hamish Avatar answered Nov 19 '22 15:11

Hamish