New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SR-8206] Block capturing unowned self crash when using it #50738
Comments
@mikeash, is this familiar? |
My understanding is that this is expected behavior. ObjC ARC will not release strong references until the end of the full statement, but Swift ARC can (intentionally) release strong references right after the last use. I suspect the first example is working because of a quirk of top-level declarations (maybe it's being treated like a global?) or just ARC optimization not happening. You can use
|
Oops, that's what I get for not reading the example carefully enough. Mike is correct. |
Thank you for explanation. I agreed that this should be expected behavior. The cause of misunderstanding this behavior is MustacheBox(message: "1").render("2") looks like "method calling on a newly created object". However it is actually "get the closure property of a newly created object and execute it". Calling a method instand works as expected. I also tried to wrap test code in a function, It seems this behavior has nothing to do with top-level declaration. My understanding is that swift does not guarantee that it release unretained objet as soon as possible, so there is chance that swift will let an object live longer. But developers should not depending on this behavior because it may change over time. import Foundation
public typealias RenderFunction = (_ info: String) throws -> String
class MustacheBox: NSObject {
var render: RenderFunction
init(message: String) {
self.render = { (_) in return "" }
super.init()
self.render = { [unowned self] (info: String) in
print(message)
print(self)
return info
}
}
func render2(_ info: String) throws -> String {
return try self.render(info)
}
}
func run() throws {
let box = MustacheBox(message: "1")
let result0 = try box.render("2")
print("This works as expected.")
let result1 = try MustacheBox(message: "1").render2("2")
print("This works as expected.")
let result2 = try MustacheBox(message: "1").render("2")
print("This will crash on swift 4.2.")
}
try run() |
Yes, I don't think it's guaranteed that the release happens as soon as possible, it's just an option. If you want to experiment, you might also try enabling optimization to see if that changes the behavior. |
Release build with `-O` gives the same result. Anyway, thank you for your kindly and timely reply. (Reopen this issue in case others want to talk on it. Feel free to close this issue at any time. ) p.s. this reply is delayed because I don't know emoji is not supported by JIRA. |
I thought closed JIRA issue could not be commented so I reopened the issue to enable further conversaion. Actually it could, so there is no reason to keep this open. |
Environment
Xcode Version 10.0 beta 3 (10L201y)
`swift --version`:
Additional Detail from JIRA
md5: 22dd0632ca3ec2b23ddb3f869cc791c0
Issue Description:
testCrash.swift
Output of `swift testCrash.swift`:
The text was updated successfully, but these errors were encountered: