Why Is There a Memory Leak at String Creation in Swift

Why is there a memory leak at String creation in swift?

I tested your code and gone through few threads and my understanding is that you have to optional binding if let clause, when using string interpolation instead of using optional variables directly. For String concatenation, if we use optionals directly there is no problem. The problem is with interpolation.

var description: String {
if let id = self.id, let name = self.name {
return "(\(id)) \(name)"
}
return "NO AVAILABLE DESCRIPTION"
}

You may get more info here memory leak in Swift String interpolation.
Seems like a bug and may be in future release it will be solved.

Why storing substrings may lead to memory leak in Swift?

Swift Arrays, Sets, Dictionaries and Strings have value semantics, but they're actually copy-on-write wrappers for reference types. In other words, they're all struct wrappers around a class. This allows the following to work without making a copy:

let foo = "ABCDEFG"
let bar = foo

When you write to a String, it uses the standard library function isUniquelyReferencedNonObjC (unless it's been renamed again) to check if there are multiple references to the backing object. If so, it creates a copy before modifying it.

var foo = "ABCDEFG"
var bar = foo // no copy (yet)
bar += "HIJK" // backing object copied to keep foo and bar independent

When you use a Substring (or array slice), you get a reference to the entire backing object rather than just the bit that you want. This means that if you have a very large string and you have a substring of just 4 characters, as long as the substring is live, you're holding the entire string backing buffer in memory. This is the leak that this warns you about.

Swift - iterating through characters in string causes memory leak

It's instruments bug(there is a lot of issues). Your code is OK.

Memory leaks when using optionals in string interpolation

Answering my own question...

It seems conditional binding is the right way to go when using string interpolation, rather than using the optionals directly. Not sure why the compiler even allows that.

Note: If someone has a better answer or better explanation, please add a new answer.

init(boundHost: String?, port: UInt16)
{
if boundHost {
self.boundHost = boundHost!
}
self.port = port

if let constBoundHost = self.boundHost
{
println("Server created with host: \(constBoundHost) and port: \(self.port).")
}
else
{
println("Server created with host: * and port: \(self.port).")
}
}

Memory leak on [String] constant

I did as @werediver mentioned, added a huge loop calling this method, and the heap didn't move, nor the number of leaks, so as he mentioned, this was a misleading diagnostic. No action needed about it.

Memory leaks when assigning text to UILabel (iOS, Swift 4, Xcode 9)

Maybe I am wrong, but I think this:

Weak will not increase the reference counter. Therefore, assigning a object label to a weak var label, does not make sense. This is because weak var label will be nil, because the object you created does not have any reference (and therefore it will deinitialize)

Let's count how many reference you have in your code to your created object Label.

label = UILabel() // 1
view.addSubview(label!) // 2
var textForLabel: String? = "Hello"
label?.text = textForLabel

//attempt to free the memory
textForLabel = nil
label = nil // 1

You have 1 reference left in your view to your object Label. Before you do label = nil, call label?.removeFromSuperview(). I think than you have 0 references -> it will deinit.

edit:

Add below subclass of UILabel into your code:

class MyLabel: UILabel {
deinit {
print("I am gone!")
}
}

Change var label: UILabel? to var label: MyLabel?

And

label = UILabel() to label = MyLabel()

And check to logs. Do you see the print "I am gone!"?

Edit2: this prints "I am gone!" in a empty project with this only as code:

import UIKit

class ViewController: UIViewController {

var label: MyLabel?

override func viewDidLoad() {
super.viewDidLoad()

label = MyLabel()
view.addSubview(label!)
let textForLabel: String? = "Hello"
label?.text = textForLabel

//EDIT: added after @J.Doe and @Sh-Khan answers, but it's still leaking
label?.removeFromSuperview()
label = nil

}
}

class MyLabel: UILabel {
deinit {
print("I am gone!")
}
}


Related Topics



Leave a reply



Submit