Skip to content

[SR-15803] Deep recursion in deinit should not happen #58080

Open
@swift-ci

Description

@swift-ci
Previous ID SR-15803
Radar None
Original Reporter Stefan Springer (JIRA User)
Type Bug
Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug
Assignee None
Priority Medium

md5: f656f5102814b117be9fbb97205c3891

Issue Description:

When the removal of the only reference to an item triggers the removal of the only reference to another item and so on, we get a stack overflow of the deinits (could be implicit deinits just created by the compiler for reference counting) when this chain is long enough (depending on how "thick" each deinit is, maybe forum entry https://forums.swift.org/t/a-roadmap-for-improving-swift-performance-predictability-arc-improvements-and-ownership-control/54206 would help with that "thickness" of each item at least). See the example code down below.

See https://github.com/hatzel/swift-simple-queue/blob/6d03e672874a33d05aff4607c3d152bd5e4a2584/Sources/FifoQueue.swift#L8 what people are tying to do to circumvent this problem, but I really think this should not occur at all, my gut feeling is that these nested calls of deinits should be unnecessary (maybe think tail recursion as an analogy). There should be a more clever way to manage the reference counting.

Also see the discussion in the Swift forums: https://forums.swift.org/t/deep-recursion-in-deinit-should-not-happen/54987

(Note that although this ticket might formally count as asking for an improvement, I created the ticket as a bug report because I think the issue is quite serious.)

Example code:

class Chained {
    var next: Chained? = nil
    init() {}
}

print("building...")
var first: Chained? = Chained()
var last = first
//for _ in 1...1_000_000 { // for release mode
for _ in 1...100_000 { // for debug mode
    let next = Chained()
    last?.next = next
    last = next
}
last = nil

print("forgetting references...")
first = nil // Thread 1: EXC_BAD_ACCESS (code=2, address=0x16f603ff0)

print("done")

Metadata

Metadata

Assignees

No one assigned

    Labels

    ARCFeature: automatic reference countingbugA deviation from expected or documented behavior. Also: expected but undesirable behavior.compilerThe Swift compiler itselfcrashBug: A crash, i.e., an abnormal termination of softwaredeinitFeature: deinitializersrun-time crashBug → crash: Swift code crashed during execution

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions