Lev
Lev

Reputation: 1930

Is passing a string back to the calling code necessary in FFI modules to prevent memory leaks?

I have

lib.rs

#[no_mangle]
pub extern "C" fn test() -> *const c_char {
    CString::from("Hello").unwrap().into_raw()
}

In Ruby, I call it as

main.rb

require 'ffi'

module Rust
   extend FFI::Library

   # [redacted loading the library]

   attach_function :test, [], :string
end

some_string = Rust::test()

Do I have to pass the string back to Rust to be freed? Won't garbage collection pick this some_string up and free it?

I'm using The Rust FFI Omnibus as a reference. I ran valgrind ruby main.rb and it didn't seem to find any leaks.

Upvotes: 1

Views: 119

Answers (1)

Shepmaster
Shepmaster

Reputation: 430584

Do I have to pass the string back to Rust to be freed?

Yes.

Won't garbage collection pick this some_string up and free it?

Yes, but that's not the memory leak to worry about. The garbage collector will free the memory allocated by Ruby that contains the transformed Ruby string.

However, the garbage collector has no knowledge of the allocation that Rust made. Specifically, the Rust code might not even have made an allocation. In that case, if the calling code freed the string, that would cause memory unsafety, so the FFI library cannot assume that this char * was an allocation.

Even if it did, it wouldn't know which allocator to use to deallocate with. Remember that there are frequently multiple allocators in play in a moderately complex application.

Disclaimer: I'm the author of the Omnibus.

Upvotes: 2

Related Questions