Skip to content
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-5511] Weak reference retains deallocated NSString (XC9 + iOS Sim only) #48083

Closed
pcantrell opened this issue Jul 19, 2017 · 6 comments
Closed
Assignees

Comments

@pcantrell
Copy link

@pcantrell pcantrell commented Jul 19, 2017

Previous ID SR-5511
Radar None
Original Reporter @pcantrell
Type Bug
Status Resolved
Resolution Invalid
Environment

Xcode 9 beta 3
Swift 4
iOS Simulator

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug
Assignee @pcantrell
Priority Medium

md5: 9046237588d6193d375e2a5ac23c2abd

Issue Description:

The following code in a playground:

import Foundation

var foo: AnyObject? = "foo" as NSString
weak var fooWeak = foo
print("before: \(foo) / \(fooWeak)")
foo = nil
print("after: \(foo) / \(fooWeak)")

…produces this output (as expected) on all platforms in XC8, and on macOS in XC9:

before: Optional(foo) / Optional(foo)
after: nil / nil

…but using the iOS Simulator in XC9, the weak ref doesn’t get nilled out:

before: Optional(foo) / Optional(foo)
after: nil / Optional(foo)
@belkadan
Copy link
Contributor

@belkadan belkadan commented Jul 19, 2017

I get that for macOS as well when executed in its own script file. Does seem a little weird. @jckarter, @slavapestov, any ideas?

@jckarter
Copy link
Member

@jckarter jckarter commented Jul 19, 2017

Did it get autoreleased? It's unlikely, but the compiler has the theoretical right to push the release past the imminent end of the program as well.

@jckarter
Copy link
Member

@jckarter jckarter commented Jul 19, 2017

Well, I get the same output with this:

import Foundation

var foo: AnyObject?
weak var fooWeak: AnyObject?
autoreleasepool {
  foo = "foo" as NSString
  fooWeak = foo
  print("before: \(foo) / \(fooWeak)")
  foo = nil
}
print("after: \(foo) / \(fooWeak)")

@gparker42, is there anything different about weak refs in the simulator that you're aware of?

@gparker42
Copy link
Mannequin

@gparker42 gparker42 mannequin commented Jul 20, 2017

You're probably being fooled by some immortal string optimization such as tagged pointers or string ROM. Try string values that are longer and less likely to be shared.

I get the following behavior from Joe's arrangement on macOS:

before: Optional(foo) / Optional(foo)
after: nil / Optional(foo)

before: Optional(foo1234!@#$) / Optional(foo1234!@#$)
after: nil / nil

@jckarter
Copy link
Member

@jckarter jckarter commented Jul 20, 2017

Ah, that makes sense. Thanks Greg.

@pcantrell
Copy link
Author

@pcantrell pcantrell commented Jul 20, 2017

Yeah, immortal strings sound like a good theory. Even this gives the expected result!

let x = "foo"
var foo: NSObject? = x as NSString
weak var fooWeak = foo
print("---------> before foo set to nil: \(foo) / \(fooWeak)")
foo = nil
print("---------> after foo set to nil: \(foo) / \(fooWeak)")

Thanks, Greg. And everyone!

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants