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-3048] Memory corruption in closures taking instances of inout classes #45638

Closed
akashivskyy opened this issue Oct 25, 2016 · 0 comments
Closed
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior.

Comments

@akashivskyy
Copy link

Previous ID SR-3048
Radar None
Original Reporter @akashivskyy
Type Bug
Status Resolved
Resolution Duplicate
Environment

macOS 10.12 (16A323)
Xcode 8.0 (8A218a)
Apple Swift version 3.0 (swiftlang-800.0.46.2 clang-800.0.38)

Additional Detail from JIRA
Votes 0
Component/s
Labels Bug
Assignee None
Priority Medium

md5: 04ee089f1aadca2513f2f24eb7e7ee07

duplicates:

  • SR-2773 function abnormally releasing instance.

Issue Description:

Details

Consider the following function, taking a subject and modifying it in place using a provided closure:

func modify<T>(_ subject: T, _ closure: (inout T) -> Void) -> T {
    var subject = subject
    closure(&subject)
    return subject
}

Then, consider the following code that uses that function:

class Foo {
    var bar: Int = 1
}
let a = modify(Foo()) { (i: inout Foo) in
    i.bar = 2
}

The value of a.bar in the above example is 2, as expected.

However, after removing (i: inout Foo) in, which should be inferred by the compiler, the following code successfully compiles and crashes at runtime with a memory corruption error:

let b = with(Foo()) {
    $0.bar = 2
}
*** error for object 0x608000030a04: Invalid pointer dequeued from free list
*** set a breakpoint in malloc_error_break to debug

Workarounds

The following special overload of modify function produces the expected result with the same test code (b) as above:

func modify<T: AnyObject>(_ subject: T, _ closure: (T) -> Void) -> T {
    closure(subject)
    return subject
}
let b = modify(Foo()) {
    $0.bar = 2
}

The value of b.bar in this case is 2, as expected.

Possibly connected issue

The above bug seems connected with the requirement to explicitly write (foo: inout Bar) in every time a closure mutates something in place, no matter if it's a struct or a class. This is not the expected behavior, though, as the compiler should automatically infer (from the closure's type) that the parameter is inout.

@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
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior.
Projects
None yet
Development

No branches or pull requests

1 participant