[swift-evolution] Should Swift apply "statement scope" for ARC

Xiaodi Wu xiaodi.wu at gmail.com
Wed Sep 21 17:14:02 CDT 2016


I haven't used it myself, but is this the use case addressed by
`withExtendedLifetime(_:_:)`?

On Wed, Sep 21, 2016 at 16:54 John Holdsworth via swift-evolution <
swift-evolution at swift.org> wrote:

> 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
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160921/8d09f0f8/attachment.html>


More information about the swift-evolution mailing list