2

When I run the below program, it produces segmentation fault. Can you please help me figure out why? Thanks

class Animal:NSObject{
    var  name:String!
    var age:UInt!

    weak var spouse:Animal?
    init(name:String,age:UInt){
        self.name=name
        self.age=age
    }

    func description() ->String{ //to become printable
        return "name= \(name) and age=\(age) spouse=\(spouse)"
    }
}


let dog=Animal(name:"Lucky",age:3)
let cat=Animal(name:"Branson",age:4)
dog.spouse=cat
cat.spouse=dog //It doesnt crash if I comment this line out
println(dog)
Airspeed Velocity
  • 40,491
  • 8
  • 113
  • 118
simplytunde
  • 197
  • 2
  • 7

2 Answers2

4

The problem is infinite recursion in your printing. Once you set up the full cycle, to print an animal, you print its spouse, which prints its spouse, which print’s its spouse etc. forever until you run out of stack space and crash.

You need to break that by printing out an animal’s spouse without calling the full print of that animal, something like this:

class Animal: NSObject {
    // you should avoid using implicitly unwrapped optionals
    // unless you absolutely have to for a specific reason that
    // doesn’t appear to apply here (so remove the !s)
    var name: String
    var age: UInt
    weak var spouse: Animal?

    init(name: String, age: UInt) {
        self.name = name
        self.age = age
    }
}

// to make something printable, you need to conform
// to the Printable protocol
extension Animal: Printable {
    // And make description is a var rather than a function
    override var description: String {
        let spousal_status = spouse?.name ?? "None"
        return "name=\(name) and age=\(age), spouse=\(spousal_status)"
    }
}


let dog = Animal(name: "Lucky", age: 3)
let cat = Animal(name: "Branson", age: 4)
dog.spouse = cat
dog.description
cat.spouse = dog
println(dog)  // Prints name=Lucky and age=3, spouse=Branson

Note, you have to implement Printable fully with the protocol and var to avoid this problem, otherwise you’ll get the default implementation, which will still experience the issue.

btw, Swift style convention is to put spaces between things like =, ->, before { etc. (and in fact you can occasionally cause compilation problems if you don’t). Jury’s still out on a: b vs a:b though I find the latter a bit harder to read.

Airspeed Velocity
  • 40,491
  • 8
  • 113
  • 118
  • Thank you very much. I released my mistake yesterday and was able to correct it in my code. Really appreciate your feedback thanks. – simplytunde Jan 05 '15 at 06:19
  • You’re welcome. Just a Stack Overflow tip – the way to thank someone who answers your question well is to accept the answer. This helps others see that the answer given did answer the question (for you, anyway – it doesn’t mean the answer is completely correct :) – Airspeed Velocity Jan 05 '15 at 12:29
0

Your code triggers a stack overflow. The description method contains the spouse description, which will in turn trigger the description of its spouse and so on in a never ending cycle. Try this:

func description() -> String {
  return "name= \(name) and age=\(age) spouse=\(spouse?.name)"
}
lassej
  • 6,256
  • 6
  • 26
  • 34