2015-06-03 5 views
14

Ich entwickle eine Anwendung in Swift 2 (Xcode 7 Beta 3) und ich versuche, Werttypen (Structs und Enums) wo möglich zu verwenden. Laut der Dokumentation von Apple über Speicherverwaltung sollte das Arbeiten mit Werttypen keine Aufbewahrungszyklen verursachen und es sollte einfach funktionieren.Speicherleck in Swift-Strukturen - Wie behebt man das?

Aber heute habe ich eine große Menge an Speicherlecks in Ereignisbehandlungscode festgestellt. Ich habe es aufgespürt und das Problem auf das folgende minimale Beispiel reduziert.

Lasst uns sagen, dass es ein Protokoll Item ist die value eine einzige Eigenschaft definiert:

protocol Item { 

    var value: String { get } 

} 

Wir haben dann eine konkrete Struktur schaffen, die das Item-Protokoll implementiert und fügt eine zusätzliche Eigenschaft additionalValue. Nennen wir die Struktur FooItem.

struct FooItem<T>: Item { 

    let value: String 
    let additionalValue: T 

    init(value: String, additionalValue: T) { 
     self.value = value 
     self.additionalValue = additionalValue 
    } 

} 

Das dritte Stück des Puzzles ist eine andere Struktur, die ein Element der Umsetzung des Item Protokoll wickelt. Es heißt ItemWrapper.

struct ItemWrapper { 

    let item: Item 

    init(item: Item) { 
     self.item = item 
    } 

} 

Wenn in Instruments profiliert erscheint der Memory-Leaks-Konfiguration verwendet wird, kann ein Speicherverlust jedes Mal ein ItemWrapper Wert mit einem FooItem erstellt wird.

let item = FooItem(value: "protocol value", additionalValue: "foo item value") 
let _ = ItemWrapper(item: item) 

Instruments screenshot 1 Instruments screenshot 2

Hier ist das Beispiel Xcode Projekt und die Instruments Datei: https://www.dropbox.com/s/z6ugxzxqggrv1xl/SwiftStructsMemoryLeak.zip?dl=0

Das ganze Codebeispiel kann in diesem Gist eingesehen werden: https://gist.github.com/lukaskubanek/4e3f7657864103d79e3a

Hier ist der Fehlerbericht: rdar: // 21375421

Ist es ein Fehler im Swift-Compiler oder mache ich etwas falsch?


EDIT 1: Wie in den Kommentaren vorgeschlagen, reposted ich diese Frage auf das Apple-Dev Forum, um mehr Aufmerksamkeit von der Swift-Community zu ziehen und möglicherweise von den Entwicklern der Sprache. Aufgrund einer Migration der Dev-Foren während der WWDC 2015 musste ich eine aktualisierte Frage zu den neuen Foren stellen. Hier ist der Link: https://forums.developer.apple.com/message/9643


EDIT 2: Das Problem, das ich ursprünglich im Beispielcode geschrieben scheint in Swift 2.0 gelöst werden. Da es die Probleme in meiner App nicht gelöst hat, habe ich eine weitere Änderung am Beispielcode vorgenommen. Jetzt hat die zusätzliche Eigenschaft FooItem einen generischen Typ und FooItem wird mit dem Typ und somit einem generischen Typ kommentiert. Dies ist, wie ich es in meiner App verwende und es immer noch einen Speicherverlust verursacht, aber dieses Mal, wenn die ItemWrapper initialisiert wird und nicht beim Zugriff auf die Eigenschaft.


EDIT 3: Voll die Frage an das modifizierte Problem aktualisiert, die 2.0 in Swift weiterhin besteht und neues Beispiel Xcode Projekt hochgeladen.

+0

Was meinen Sie an anderer Stelle durch - im Code oder für weitere Ressourcen zum Thema auf anderen Websites? –

+0

Das Beispiel ist eigentlich nur diese 3 Entitäten und der Code, der sie aufruft. Sieh dieses Gist https://gist.github.com/lukaskubanek/4e3f7657864103d79e3a für das ganze AppDelegate. Entschuldige, dass ich es in der Frage nicht erwähnt habe. –

+0

Ich konnte das Problem reproduzieren, aber keine Ahnung, was zur Hölle los ist .. +1 – Mazyod

Antwort

4

Obwohl ich keine Antwort von Apple weder auf den Dev-Foren noch im Bug-Tracker bekommen habe und ich in den Versionshinweisen der neuesten Beta-Versionen nichts zu diesem Thema gefunden habe, scheint es gelöst zu sein im Swift-Compiler in Xcode 7 Beta 5. (Vielleicht funktioniert es auch in Beta 4. Die letzte Version, die ich überprüft habe, war Beta 3.)

Das Demo-Projekt erzeugt das Speicherleck nicht mehr. Das Gleiche gilt für meine App. Yay!

enter image description here

3

Nun, hier ist ein Workaround, obwohl ich keine Ahnung habe, warum es funktioniert. Ich habe bemerkt, dass, wenn Sie dies tun:

let theItem = itemWrapper.item 
    let value = theItem.value 

... statt dessen:

let value = itemWrapper.item.value 

... es erzeugt nicht den Speicherverlust.

+0

Ich fand diese Problemumgehung auch. Das Problem ist, dass dies nur für Eigenschaften funktioniert. In meinem realen Code habe ich auch Methoden im Protokoll definiert und sie generieren auch Speicherlecks. Also musste ich Funktionen schreiben, die alle konkreten Typen (wie 'FooItem' usw.) umhüllen und das macht keinen Spaß. –

+0

Aber danke für den schönen Fang! ;-) –

+0

Ja. Meine Vermutung ist, dass es nur ein Fehler im Swift-Compiler ist, der (hoffentlich) irgendwann behoben wird, und die "Lösung" besteht darin, einfach ein Radar zu posten und darauf zu warten, dass Apple es anspricht. (Es gibt * eine Compiler-Direktive, mit der Sie "Swift Optimizations" aktivieren können, die Ihnen einen anderen Build geben. Sie könnten versuchen, das einzuschalten und zu sehen, ob das behebt. Aber seien Sie gewarnt, dass auch einige bekannte Probleme auftreten könnte ein Kompromiss sein.) –