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

memory leak... #2

Closed
jjjkkkjjj opened this issue Mar 2, 2020 · 9 comments
Closed

memory leak... #2

jjjkkkjjj opened this issue Mar 2, 2020 · 9 comments
Labels
bug Something isn't working

Comments

@jjjkkkjjj
Copy link
Owner

I wrote pointer's value without initializing, too many many many memory leaks were occurred :)

See ref
Use move or initialize first.

Bad code eg. here, here, here #

@jjjkkkjjj jjjkkkjjj added the bug Something isn't working label Mar 2, 2020
@jjjkkkjjj
Copy link
Owner Author

//
//  memory.swift
//  pointer-sample

import Foundation

class Memory{
    
    init() {
        print("init")
    }
    
    deinit {
        print("deinit")
    }
}

class ShapeDummy{
    
    init() {
        print("ShapeDummy init")
    }
    
    deinit {
        print("ShapeDummy deinit")
    }
}



class MemPointer{
    var ptr: UnsafeMutableRawBufferPointer
    var shapeptr: UnsafeMutableBufferPointer<ShapeDummy>
    
    init(_ array: [Memory], shape: [ShapeDummy]) {
        
        let ptr = create_unsafeMRBPtr(type: Memory.Type.self, count: array.count)
        array.withUnsafeBytes{
            memcpy(ptr.baseAddress!, $0.baseAddress, ptr.count)
        }
        
        let sptr = create_unsafeMBPtrT(type: ShapeDummy.self, count: shape.count)
        var shape = shape
        self.shapeptr = array2UnsafeMBPtrT(&shape)
        
        self.ptr = ptr
>>>>>>>>>>>>>>>>>>>>>>        
        self.shapeptr[0] = ShapeDummy() //-> leak!
>>>>>>>>>>>>>>>>>>>>>>
    }
    
    deinit {
        self.ptr.deallocate()
    }
}

//Note that returned value (UnsafeMutableBufferPointer<T>) will not be freed and was not initialized
internal func create_unsafeMBPtrT<T>(type: T.Type, count: Int) -> UnsafeMutableBufferPointer<T>{
    typealias pointer = UnsafeMutableBufferPointer<T>
    return pointer.allocate(capacity: count)
}

//Note that returned value (UnsafeMutableRawBufferPointer) will not be freed and was not initialized
internal func create_unsafeMRBPtr<T>(type: T.Type, count: Int) -> UnsafeMutableRawBufferPointer{
    typealias pointer = UnsafeMutableRawBufferPointer
    return pointer.allocate(byteCount: MemoryLayout<T>.stride * count, alignment: MemoryLayout<T>.alignment)
}

internal func array2UnsafeMBPtrT<T>(_ array: inout [T]) -> UnsafeMutableBufferPointer<T>{
    let ptr = create_unsafeMBPtrT(type: T.self, count: array.count)
    let _ = array.withUnsafeMutableBytes{
        memcpy(ptr.baseAddress!, $0.baseAddress!, $0.count)
    }
    return ptr
}

@jjjkkkjjj
Copy link
Owner Author

In the first place, I shouldn't set property as pointer...
link

@jjjkkkjjj
Copy link
Owner Author

jjjkkkjjj commented Mar 3, 2020

class MemPointer{
    var ptr: UnsafeMutableRawBufferPointer
    var shapeptr: UnsafeMutableBufferPointer<ShapeDummy>
    
    init(_ array: [Memory], shape: [ShapeDummy]) {
        
        let ptr = create_unsafeMRBPtr(type: Memory.Type.self, count: array.count)
        array.withUnsafeBytes{
            memcpy(ptr.baseAddress!, $0.baseAddress, ptr.count)
        }
        
        let sptr = create_unsafeMBPtrT(type: ShapeDummy.self, count: shape.count)
        var shape = shape
        self.shapeptr = array2UnsafeMBPtrT(&shape)
        
        self.ptr = ptr
>>>>>>>>>>>>>>>>>>>>>>        
        self.shapeptr[0] = ShapeDummy() //-> leak!
>>>>>>>>>>>>>>>>>>>>>>
    }
    
    deinit {
        self.ptr.deallocate()
    }
}

prevent memory leak by this

self.shapeptr.deinitialize(count: 3)

I must destroy "stored" data

@jjjkkkjjj
Copy link
Owner Author

class MemPointer{
    var ptr: UnsafeMutableRawPointer
    var shapeptr: UnsafeMutablePointer<ShapeDummy>
    
    init(_ array: [Memory], shape: [ShapeDummy]) {
        
        var array = array
        self.ptr = array2UnsafeMRPtr(&array)
        print(self.ptr.bindMemory(to: Memory.self, capacity: 4)[3].mycnt)
        self.ptr.bindMemory(to: Memory.self, capacity: 4)[3] = Memory()
        print(self.ptr.bindMemory(to: Memory.self, capacity: 4)[3].mycnt)
        //let sptr = create_unsafeMPtrT(type: ShapeDummy.self, count: shape.count)
        var shape = shape
        self.shapeptr = array2UnsafeMPtrT(&shape)

        self.shapeptr.pointee = ShapeDummy()

        print(self.shapeptr[1].mycnt)
        //self.shapeptr.move()
    }
    
    deinit {
        print("Mempointer deconstructor called")
        self.ptr.bindMemory(to: Memory.self, capacity: 4).deinitialize(count: 4)
        self.ptr.deallocate()
        self.shapeptr.deinitialize(count: 3)
        self.shapeptr.deallocate()
    }
}

//Note that returned value (UnsafeMutableBufferPointer<T>) will not be freed and was not initialized
internal func create_unsafeMPtrT<T>(init_value: T, count: Int) -> UnsafeMutablePointer<T>{
    typealias pointer = UnsafeMutablePointer<T>
    
    let ptr = pointer.allocate(capacity: count)

    ptr.initialize(repeating: init_value, count: count)
    return ptr
}

//Note that returned value (UnsafeMutableRawBufferPointer) will not be freed and was not initialized
internal func create_unsafeMRPtr<T>(init_value: T, count: Int) -> UnsafeMutableRawPointer{
    typealias pointer = UnsafeMutableRawPointer
    let ptr = pointer.allocate(byteCount: MemoryLayout<T>.stride * count, alignment: MemoryLayout<T>.alignment)
    ptr.initializeMemory(as: T.self, repeating: init_value, count: count)
    return ptr
}

internal func array2UnsafeMPtrT<T>(_ array: inout [T]) -> UnsafeMutablePointer<T>{
    let ptr = create_unsafeMPtrT(init_value: array.first!, count: array.count)
    
    let _ = array.withUnsafeMutableBufferPointer{
        //memcpy(ptr, $0.baseAddress!, $0.count)
        ptr.assign(from: $0.baseAddress!, count: $0.count)
        //ptr.moveInitialize(from: $0.baseAddress!, count: $0.count)
    }
    return ptr
}

internal func array2UnsafeMRPtr<T>(_ array: inout [T]) -> UnsafeMutableRawPointer{
    let ptr = create_unsafeMRPtr(init_value: array.first!, count: array.count)
    let ret = ptr.bindMemory(to: T.self, capacity: array.count)
    let _ = array.withUnsafeMutableBufferPointer{
        //memcpy(ptr, $0.baseAddress!, $0.count)
        ret.assign(from: $0.baseAddress!, count: $0.count)
        //ptr.moveInitialize(from: $0.baseAddress!, count: $0.count)
    }
    return ptr
}

Log was

Memory0 init
Memory1 init
Memory2 init
Memory3 init
ShapeDummy0 init
ShapeDummy1 init
ShapeDummy2 init
3
Memory4 init
4
ShapeDummy3 init
1
ShapeDummy0 deinit
Memory3 deinit
Mempointer deconstructor called
Memory0 deinit
Memory1 deinit
Memory2 deinit
Memory4 deinit
ShapeDummy3 deinit
ShapeDummy1 deinit
ShapeDummy2 deinit

I must initialize memory first by padding anything?

@jjjkkkjjj
Copy link
Owner Author

jjjkkkjjj commented Mar 3, 2020

    var tmp = [Memory(), Memory(), Memory(), Memory()]
    var copptr = array2UnsafeMRPtr(&tmp)
    //self.memory.copyMemory(from: copptr, byteCount: MemoryLayout<Memory>.size * 4)// leak!
    self.memory.bindMemory(to: Memory.self, capacity: 4).assign(from: copptr.bindMemory(to: Memory.self, capacity: 4), count: 4)//->ok!
        
        
    copptr.bindMemory(to: Memory.self, capacity: 4).deinitialize(count: 4)
    copptr.deallocate()
}
deinit {
        print("Mempointer deconstructor called")
        self.shapeptr.deinitialize(count: 3)
        self.shapeptr.deallocate()
        
        self.memory.assumingMemoryBound(to: Memory.self).deinitialize(count: 4)
        self.memory.deallocate()
    }

No leak!

@jjjkkkjjj
Copy link
Owner Author

I can't pursue leak's reason.
I had better use normal array?

@jjjkkkjjj
Copy link
Owner Author

jjjkkkjjj commented Mar 10, 2020

The reason of problem may be editing shapeptr directly.
I should use "with" function such like

public func withShapeMBPtr<R>(_ body: (UnsafeMutableBufferPointer<Int>) throws -> R) rethrows -> R{
    try self.shape.withUnsafeMutableBufferPointer{
        try body($0)
    }
} 

jjjkkkjjj pushed a commit that referenced this issue Mar 12, 2020
@jjjkkkjjj
Copy link
Owner Author

        let e = Matft.mfarray.arange(start: 0, stop: 27, step: 1, shape: [3,3,3])
        
        print(e[-2~1])
        print(e[-4~1])
        print(e[-1~1])
        print(e[0~4])
        print(e[-1~~-1])
        print(e[-2~0~-1])
        print(e[2~0~-1])
        print(e[-1~-8~-1])
        print(e[-8~0~-1])
        
        print(e[1,1,1])
        e[1,1] = 5
        print(e)
        
        let d = Matft.mfarray.conv_order(e[-1~~-1], mforder: .Row)
        print(d)
        print(e.T)
        print(e.T + e[-4~1]) ///->>>>> crash!

@jjjkkkjjj
Copy link
Owner Author

        let d = Matft.mfarray.conv_order(e[-1~~-1], mforder: .Row)
        print(d)
        print(e.T)
        print(e.T + e[-4~1]) ///->>>>> crash!

this one is merely bug.
I think this issue has already resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant