Search code examples
swiftmemory-managementunsafe-pointers

Automatically handling disposing of unsafe allocated memory in Swift


In a Swift program that interacts with low level operating system functions, I allocate "Unsafe" memory blocks in order to buffer data. These blocks are stored in a struct that can be passed around various parts of the program. How can I track these copies and ensure the memory block is deallocated once all the copies are finished with?

Example code:

struct Packet {
    var memoryBlock : UnsafeRawPointer
    init () {
        let block = UnsafeMutableRawPointer.allocate (bytes: 128, alignedTo: 4)
        someProcessThatFillsTheBuffer (block); 
        memoryBlock = UnsafeRawPointer(block);
    }
}

let packet = Packet()
process1.handle (packet); process2.handle (packet)

How can I ensure the allocated block is disposed of once both process1 and process2 have finished with it?

In C++, I'd use a shared_ptr to track the allocation. Does Swift have something similar I can use for this? Some way of using the existing ARC system to do it?


Solution

  • You can define a class instead and release the memory in deinit:

    class Packet {
        var memoryBlock : UnsafeRawPointer
        init() {
            let block = UnsafeMutableRawPointer.allocate(byteCount: 128, alignment: 4)
            //someProcessThatFillsTheBuffer (block);
            memoryBlock = UnsafeRawPointer(block);
        }
    
        deinit {
            memoryBlock.deallocate()
        }
    }
    

    Now instances of Packet are references to an object and can be passed around. ARC (automatic reference counting) ensures that deinit is called when the last reference to the object is gone.