Discarding deep recursive enum causes EXC_BAD_ACCESS

I only started with Swift and iOS/OS X development a few days ago, so I don't know the procedure for reporting these things, or where to check if it is a known problem.


If I create a recursive enum that is deep enough – the smaller the enum, the deeper the recursion needed – I get a runtime segfault, but only when the instance is no longer referenced.


It is the very last line that crashes. Creating the large structure works fine. I can also traverse it, no problem. But when I throw it away, I get a crash.


enum Rec {
    case Nil
    indirect case Wrap(Rec)
    init(count: Int) {
        self = Nil
        for _ in 1...count {
            self = Wrap(self)
        }
    }
}
var rec: Rec
rec = Rec(count: 300_000)
rec = .Nil


This is with Xcode 7.1.

Your code makes no sense to me, but at the very bottom of the webpage you'll see a "Report Bugs" link if you really think it's a bug.

One thing important is that

Discarding deep recursive class also causes EXC_BAD_ACCESS.


(Mistakenly pushed Add Reply here...)


class Chain {
    var child: Chain?
    init() {}
    init(count: Int) {
        var tmp = self
        for _ in 1...count {
            let next = Chain()
            tmp.child = next
            tmp = next
        }
    }
}
var chain: Chain? = Chain(count: 300_000)
chain = nil //->EXC_BAD_ACCESS

A simple implementation of `release` calls `release` recursively, so releasing too deep recursive structure causes stackoverflow -- EXC_BAD_ACCESS.

(Not much documented, but I believe indirect enum values are managed in a similar manner as reference-counting.)


You can (and need to) write a safe releasing method for simple recursive classes:

class Chain {
    var child: Chain?
    init() {}
    init(count: Int) {
        var tmp = self
        for _ in 1...count {
            let next = Chain()
            tmp.child = next
            tmp = next
        }
    }
   
    func releaseSafe() {
        var arr: [Chain] = []
        var tmp = self
        while let next = tmp.child {
            arr.append(tmp)
            tmp = next
        }
        while let last = arr.popLast() {
            last.child = nil
        }
    }
}
var chain: Chain? = Chain(count: 300_000)
chain!.releaseSafe()
chain = nil

(Though, it is not easy to write non-stack-consuming `release` for complex structures.)


But, I don't know if we can write a similar method as `releaseSafe` above, for recursive enums.

In the case of recursive classes, is this a limitation that is recognized by Apple? It seems like a clear bug to me, but I work mainly in functional languages where recursion is a staple.


I came up with this releaseSafe() for my enum example. It just walks the chain backwards and releases one step at a time. But now we are back to manual memory management.


enum Rec {
    case Nil
    indirect case Wrap(Rec)

    init(count: Int) {
        self = Nil
        for _ in 1...count {
            self = Wrap(self)
        }
    }

    mutating func releaseSafe() {
        while case let .Wrap(wrapped) = self {
            self = wrapped
        }
    }
}

In the case of recursive classes, is this a limitation that is recognized by Apple?

Just my guess, though I'm very sure, Apple is recognizing the limitation. In the former primary language of Apple, Objective-C, we needed to write retain and release explicitly and had to implement dealloc ourselves.

Swift has many features inspired by functional languages (or other scripting languages), but Swift itself is not a functional language.


In my opinion, Swift is more C than F, it's an advanced C rather than a functional language.

So, we need to fill in the gap manually, if we get beyond the edge of the Swift limitation.

(By the way, your way of `safe release` looks smarter than mine.)

Discarding deep recursive enum causes EXC_BAD_ACCESS
 
 
Q