Swift, C, and memory leaks

I have this code in a network extension:

private func pathForToken(token: audit_token_t) -> String? {
    var tokenCopy = token
    let bufferSize = UInt32(4096)
    let bytes = UnsafeMutablePointer<UInt8>.allocate(capacity: Int(bufferSize))
    let length = proc_pidpath_audittoken(&tokenCopy, bytes, bufferSize)
    if length != 0 {
        return String(cString: bytes).lowercased()
    }
    return nil
}

bytes appears to be leaked -- the call stack is pathForToken(token:) to specialized static UnsafeMutablePointer.allocate(capacity:)

Do I need to do something to ensure bytes is released, since it doesn't seem to be happening on its own?

Answered by Scott in 783891022

Do I need to do something to ensure bytes is released, since it doesn't seem to be happening on its own?

Definitely! See this note in the documentation for UnsafeMutablePointer.allocate(capacity:):

When you allocate memory, always remember to deallocate once you’re finished.

The Unsafe in the name is a reminder you’re in old-school C land now, where you need to free() at some point after every malloc().

Accepted Answer

Do I need to do something to ensure bytes is released, since it doesn't seem to be happening on its own?

Definitely! See this note in the documentation for UnsafeMutablePointer.allocate(capacity:):

When you allocate memory, always remember to deallocate once you’re finished.

The Unsafe in the name is a reminder you’re in old-school C land now, where you need to free() at some point after every malloc().

Yeah I just found that, and confirmed it worked. 😊

None of the examples I'd, ahem, borrowed from seem to have had the call, so I assumed it was all handled via ARC.

If I were doing this I’d avoid the whole issue by getting Swift to manage the memory for me:

func pathForToken(token: audit_token_t) -> String? {
    var tokenCopy = token
    var buffer = [CChar](repeating: 0, count: 4096)
    let length = proc_pidpath_audittoken(&tokenCopy, &buffer, UInt32(buffer.count))
    guard length > 0 else { return nil }
    return String(utf8String: buffer)
}

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Ok that is much nicer indeed.

Swift, C, and memory leaks
 
 
Q