Debugger Reporting Wrong Values For Properties In Swift

We're experiencing some weird issues with the Xcode debugger reporting incorrect values for properties in certain circumstances. Here's a tiny concrete example that illusrates the problem (it works for both MacOS and iOS)...


Say you have a Protocol lke this...


import Foundation
protocol MyProtocol {

    func aProtocolFunction()
}


And a Struct like this, which conforms to the Protocol, like this...


import Foundation
struct MyStruct: MyProtocol {

    var property1 = [Float]()
    var property2 = [Float]()
    var property3 = [Float]()
    var property4 = [Float]()

    func aProtocolFunction() {

      //This function doesn't have to do anything
    }
}


Now, if you write some code that uses the above struct and protocol lke this, and add a break point on the line which says, "add a break point on this line" the issue we have can be observed....


   var myStruct = MyStruct()

   var myArrayOfProtocolConformingThings = [MyProtocol]()

   myStruct.property1 = [1.0]
   myStruct.property2 = [1.0, 2.0]
   myStruct.property3 = [1.0, 2.0, 3.0]
   myStruct.property4 = [1.0, 2.0, 3.0, 4.0]

   myArrayOfProtocolConformingThings.append(myStruct)

   print("Add a break point on this line")


You find that when you inspect the contents of the myArrayOfProtocolConformingThings array in the Xcode debugger, it reports completely the wrong contents for myArrayOfProtocolConformingThings[0]. Specifically, the values for property1, property2, property3 and property4 are all reported incorrectly. The debugger says that:


  • property1 is an empty array
  • property2 is an empty array
  • property3 shows the contents of property1
  • property4 shows the contents of property2


Does anyone know what's going on here? This kind of issue is making it really hard to sort out some problems in our code. We think some of the issues might be Swift compiler bugs (as well as our own bugs!), but it's really hard to know when the debugger gets things so wrong.

Replies

It looks like a bug in the debugger, or in the debug information.


When you have an array of protocol-typed elements, the actual elements are boxed structures that say what the actual type of each element is. It looks like the debugger is treating that boxed structure as if it were the type it describes, so it shows the wrong property values.


This problem still exists in Xcode 9.3 beta 1 (I'm still downloading beta 2, so I don't know if it's fixed there), but you should submit a bug report ASAP, to try to get this fixed before the final 9.3 release.


For a workaround, I found that if you display myArrayOfProtocolConformingThings in the console window using the "po" command:


     po myArrayOfProtocolConformingThings


it will show the correct information. The plain "p" command displays the wrong information.

Thanks for that, I'll submit a bug report ASAP, given I've put a simple test minimal test project together.


Yes, in this case, "printing out" the values like you suggest does work. But we have other scenarios with more complex code where:


  • In some cases, the po also fails and shows "wrong values"; but the actual code works fine.
  • In some cases it's looking to us like the Swift compiler is actually *really* screwing up operations like copying (quite complicated) structs when you assign a copy of struct to a new variable with simple code like "let a= b" (but can't yet be sure on this - the code is really complicated)


Haven't had time to try to put to simple, minimal test cases together for those yet, though.

In case anyone is interested, I just reported the bug, and the ID I got back is: 37284257

FWIW, it's wrong in 9.3 beta 2 too.


>> we have other scenarios with more complex code


You could try implementing CustomDebugStringConvertible on MyStruct. You might have to make MyProtocol conform to CustomDebugStringConvertible too, though, if the unboxing problem persists around the customized representation.

Thanks for the suggestion - that sounds like a good idea!

For anyone who cares, Apple updated the bug report I filed to say this is a duplicate of a known bug.