Skip to content

Instantly share code, notes, and snippets.

@mayoff
Created February 23, 2019 03:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mayoff/2c788003c1b5161da36bec807cc2a8e5 to your computer and use it in GitHub Desktop.
Save mayoff/2c788003c1b5161da36bec807cc2a8e5 to your computer and use it in GitHub Desktop.
test Swift unowned safety
class MyObject { }
var o = MyObject()
print("strong o = \(o)")
unowned let u = o
print("unowned u = \(u)")
o = MyObject()
print("new strong o = \(o)")
print("old unowned u = \(u)")
@robertmryan
Copy link

robertmryan commented Feb 23, 2019

@mayoff - Yeah, I got “safe” terminations with your code, above.

This is my test program:

class ViewController: NSViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        class MyObject {
            var value = 0
        }
        
        var o = MyObject()
        unowned var u = o
        u.value = 42
        o = MyObject()
        
        DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
            print("old unowned u = \(u)")
        }
    }
}

This does not do so safely. If I turn off optimizations, it is safe, but with “optimized for space”, -Osize, or “optimized for speed”, -O, I get a variety of “unsafe” crashes, e.g.

(EXC_BAD_ACCCESS (code=1; address=0x11d10a180)

Worse, if I print(u.value) instead of u, it blithely shows me random bogus numbers (e.g. 4320159368) with no error at all. All of this is traditional dangling pointer sort of behavior.

But you’re 100% right, that with a few, seemingly unrelated code changes, it appears to “safely” crash. And, of course, if you turn off optimizations, it behaves precisely as one would expect.

By the way, I got the same sorts of results with macOS and iOS targets. Xcode 10.1. macOS 10.14.3.

@hamishknight
Copy link

@robertmryan That looks like a 5.0 regression to me, as in Swift 4.2 it correctly aborts with a runtime error. I'll file a bug when I get a moment.

@robertmryan
Copy link

robertmryan commented Feb 25, 2019

@hamishknight - that was in Swift 4.2.1.

Apple Swift version 4.2.1 (swiftlang-1000.11.42 clang-1000.11.45.1)

@hamishknight
Copy link

@robertmryan Ah interesting! Sorry, I missed that part in your original post. Upon re-inspection, you get the same behaviour in 4.2 and 5.0 – it just appears to be sometimes hitting the runtime error and sometimes crashing with EXC_BAD_ACCESS. Digging a bit further, when running with an assert Swift runtime it trips an assertion.

Filed a bug: SR-9999.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment