Description
I'm using the objc crate to get the icon/image of a macos .app file.
But my following snippet leaks memory. I am fairly certain it is this snippet because if I replace the snippet with a String of b64 of the same image, no memory leak occurs.
Does this snippet use the objc crate in a wrong way? I suspect I'm not seeing something obvious in the docs.
How can I prevent this snippet from causing memory leaks?
fn get_icon_for_app_file(path: &str) -> String {
// Get a class
let ns_workspace_class = objc::class!(NSWorkspace); // NSObject
// Allocate an instance
let ns_workspace_obj = unsafe {
let obj: *mut Object = objc::msg_send![ns_workspace_class, alloc];
let obj: *mut Object = objc::msg_send![obj, init];
StrongPtr::new(obj)
};
let path = unsafe { NSString::alloc(nil).init_str(path) };
let ns_image: Id<Object> = unsafe {
let img = msg_send!(*ns_workspace_obj, iconForFile:path);
img
};
// let _: () = unsafe { msg_send![*ns_workspace_obj, release] };
// drop(ns_workspace_obj);
let foundation_ns_data: Id<Object> = unsafe {
msg_send!(ns_image, TIFFRepresentationUsingCompression:6 factor:90)
};
let ns_bitmap_image_rep: Id<Object> = unsafe {
msg_send!(class!(NSBitmapImageRep), imageRepWithData: ns_data)
};
let foundation_data: Id<Object> = unsafe {
msg_send!(ns_bitmap_image_rep, representationUsingType:3 properties:nil)
};
let b64 = unsafe {
msg_send!(data, base64EncodedStringWithOptions:nil)
};
let c_buf: *const c_char = unsafe {
// GITHUB COMMENT EDIT: renamed from about_item_prefix
let init_string = NSString::alloc(nil).init_str("");
// GITHUB COMMENT EDIT: renamed from about_item_title
let b64_string = init_string.stringByAppendingString_(b64);
let c_pointer: *const libc::c_char = b64_string.UTF8String();
c_pointer
};
let c_str: &CStr = unsafe { CStr::from_ptr(c_buf) };
let str_slice: &str = c_str.to_str().unwrap();
let mut img = String::from("data:image/jpeg;base64,");
img.push_str(str_slice);
println!("Final image data is: {}", img);
Ok(img)
}
I've tried using various expressions of let _: () = unsafe { msg_send![some_object, release] };
to release memory, but I get segmentation faults and rarely bus faults (for context this snippet is run in multithreaded env, perhaps contributing). Should the snippet be using release
, and wrapping this snippet in something like a mutex so it can only be run by 1 thread at a time?