Skip to content

How do you not cause memory leaks? #117

Closed
@selfconfigio

Description

@selfconfigio

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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions