wickwirew / Runtime

A Swift Runtime library for viewing type info, and the dynamic getting and setting of properties.
MIT License
1.08k stars 94 forks source link

Memory Leaks in property setters #64

Open robertjpayne opened 4 years ago

robertjpayne commented 4 years ago

I believe there is a memory leak with the below code:

https://github.com/wickwirew/Runtime/blob/5638402223ac41a4f3ddc45993534d8ff9c3f398/Sources/Runtime/Utilities/GettersSetters.swift#L41

I think what's happening is if the value is not initialised it will be fine and no leak will occur (construction) but if you're replacing an existing value the old value is nullified without being free'd since swift loses track of it.

robertjpayne commented 4 years ago

Ok so here is an easy to reproduce example below. You will notice the START inner value that is replaced never gets deallocated

import Runtime

class MySubObject {
    let label: String
    init(label: String) {
        self.label = label
    }

    deinit {
        print("MySubObject(label: \(self.label)) deinit")
    }
}

class MyObject {
    let inner: MySubObject

    init(label: String) {
        self.inner = MySubObject(label: label)
    }

    deinit {
        print("MyObject(inner.label: \(self.inner.label)) deinit")
    }
}

var obj: MyObject = MyObject(label: "START")

var newInner = MySubObject(label: "UPDATE")

let property = try Runtime.typeInfo(of: MyObject.self).property(named: "inner")
try property.set(value: newInner, on: &obj)

obj = MyObject(label: "FINALISE")
robertjpayne commented 4 years ago

@wickwirew would be interested if you have any thoughts on this -- it's a really tricky thing and I'm not sure there is actually any feasible solution since we can't use Unmanaged<X> or anything to try and munge the ref counting and sorts.

wickwirew commented 4 years ago

At first glance, we may just need to make a call to swift_release manually for any heap values.

robertjpayne commented 4 years ago

We ended up having to remove runtime entirely and use sourcery for our magic "reloading". Unfortunately didn't seem like there was a good fix that we felt was safe enough.

blindmonkey commented 3 years ago

We just ran into this in our project. Are there any plans to fix this? We started using Runtime pretty heavily, so I'm a bit concerned that these leaks will add up. We're thinking about using Unmanaged to work around this, but are a bit concerned that the fix will work against us if it's fixed in the library.