Convert [Int32] to UnsafeMutablePointer<Int32>

I tried:

let mib: [Int32] = [ CTL_KERN, KERN_PROCARGS, pid ]
let mibLen = UInt32(mib.count)
var length: size_t = 0
let si = sysctl( mib, mibLen, nil, &length, nil, 0)

this resulted in:

Error: Cannot convert value of type '[Int32]' to expected argument type 'UnsafeMutablePointer<Int32>?'

Then I tried:

let uMib: UnsafeMutablePointer<Int32> = UnsafeMutablePointer(mutating: mib)
let si = sysctl( uMib, mibLen, nil, &length, nil, 0)

This works, but produces:

Warning: Initialization of 'UnsafeMutablePointer<Int32>' results in a dangling pointer

What is the correct way to call sysctl() ?

sysctl() takes a mutable pointer as the first argument, so you need to declare mib as a variable and pass the address of its element storage to the function with &mib:

var mib: [Int32] = [ CTL_KERN, KERN_PROCARGS, pid ]
// ...
let si = sysctl(&mib, mibLen, nil, &length, nil, 0)

If it is guaranteed that sysctl() does not write to the mib array (what I suspect, but do not know for sure) then you can also declare it as a constant and make the pointer mutable just for the system call:

let mib: [Int32] = [ CTL_KERN, KERN_PROCARGS, pid ]
// ...
let si = mib.withUnsafeBufferPointer { p in
    sysctl(UnsafeMutablePointer(mutating: p.baseAddress), mibLen, nil, &length, nil, 0)
}
4 Likes