nh7a
1
I am trying to convert the following ObjC code to Swift and found it not as easy due to memory leak.
num_threads_objc() below works fine while num_threads_swift() below seems leaking memory according to Xcode. I suspect the use of vm_deallocate() below is wrong, but can't figure out how.
What am I missing?
int num_threads_objc() {
thread_act_array_t threads;
mach_msg_type_number_t thread_count;
if (task_threads(mach_task_self(), &threads, &thread_count) != KERN_SUCCESS) {
return -1;
}
vm_deallocate(mach_task_self(), (vm_address_t)threads, sizeof(thread_t) * thread_count);
return thread_count;
}
func num_threads_swift() -> Int {
var threads: thread_act_array_t?
var thread_count: mach_msg_type_number_t = 0
guard task_threads(mach_task_self_, &threads, &thread_count) == KERN_SUCCESS else { return -1 }
let size = MemoryLayout<thread_t>.size * Int(thread_count)
vm_deallocate(mach_task_self_, vm_address_t(threads!.pointee), vm_size_t(size))
return Int(thread_count)
}
jrose
(Jordan Rose)
2
Isn't threads the thing to convert to vm_address_t, not whatever it points to?
nh7a
3
Since threads is UnsafeMutablePointer<thread_act_t>?, isn't threads!.pointee the thing to convert and free?
Martin
(Martin R)
4
It probably should be
vm_deallocate(mach_task_self_, vm_address_t(bitPattern: threads!), vm_size_t(size))
(from C array memory deallocation from swift on Stack Overflow).
threads! is the pointer to the memory to be freed (as @jrose said), but vm_deallocate expects the address as an vm_address_t aka UInt. In (Objective-)C you can simply cast the pointer to an
integer. In Swift you need the init(bitPattern:) initializer.
2 Likes
nh7a
5
Aww. That was it. Thanks a lot! :)
NeroXie
(Nero Xie)
6
I have a question,both MemoryLayout<thread_t>.size, MemoryLayout<thread_t>.stride and sizeof(thread_t) have a value of 4, but MemoryLayout.stride and sizeof use memory alignment, so I think using MemoryLayout.stride is more accurate. This is my personal idea, can anyone explain it to me.
eskimo
(Quinn “The Eskimo!”)
7
so I think using B is more accurate
What is “B” in this context?
Share and Enjoy
Quinn “The Eskimo!” @ DTS @ Apple
NeroXie
(Nero Xie)
8
B means MemoryLayout<thread_t>.stride
eskimo
(Quinn “The Eskimo!”)
9
So, you mean:
?
If so, then yeah, using stride is probably the most correct option. However, in this case thread_t is a UInt32 [1], so it doesn’t matter. Moreover, I don’t think it will ever matter when dealing with basic Mach types like this because they never have any padding.
Share and Enjoy
Quinn “The Eskimo!” @ DTS @ Apple
[1] Via the chain thread_t > mach_port_t > __darwin_mach_port_t is __darwin_mach_port_name_t > __darwin_natural_t > UInt32, which is quite a chain!