Hi,
For complex statements in C++ any temporary instances created in the course
of an expression have their lifetime extended to the completion of the current
statement after which they are all deallocated en masse. This makes certain
types of language usage possible and easier to reason with.
I’m bringing this up as I had a problem with some code crashing only when
compiled with release configuration and the problem could have been avoided
if Swift deferred deallocation to the end of a statement. While Swift’s ARC
policy
is consistent in itself this seems to be a particular problem interfacing
between
language/reference counting systems. My problem code was a Java-Swift Bridge.
A contrived example:
import Foundation
protocol Storage {
var fp: UnsafeMutablePointer<FILE> { get }
}
class FileStorage: Storage {
let fp: UnsafeMutablePointer<FILE>
init?(path: String, mode: String = "w") {
print("Opening")
let fp = fopen(path, mode)
if fp == nil {
return nil
}
self.fp = fp!
}
deinit {
print("Closing")
fclose(fp)
}
}
func save(string: String, to: Storage?) {
if let data = string.data(using: String.Encoding.utf8) {
print("Saving1")
if let fp = to?.fp {
print("Saving2")
data.withUnsafeBytes {
_ = fwrite($0, 1, data.count, fp)
}
print("Saving3")
}
}
}
save(string: "Hello World\n", to: FileStorage(path: "/tmp/a.txt"))
In debug configuration is prints:
Opening
Saving1
Saving2
Saving3
Closing
Whereas in release configuration it prints:
Opening
Saving1
Closing <!!!
Saving2
Saving3
The optimiser is vigorously deallocating objects when they are no longer
referenced regardless
of whether an variable referencing it is still in scope (In fairness this
particular problem only occurs
for Optional augments of Protocols) but this behaviour seems to be implicit in
the current language
spec. The alternative is to retain arguments themselves as I believe they are
in Objective-C ARC.
This would have been avoided if the temporary FileStorage instance has been
considered to have
a lifetime up to the end of the statement calling function save() and hence the
duration of the call.
This needed increase ARC overhead in any way. Just alter the timing of it to be
more conservative.
John
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution