In this lesson, you will learn how to safely hand over memory management responsibilities from Rust to an external C library.
When you work with Foreign Function Interface (FFI), you are stepping outside of Rust’s "safety net." C libraries don't know about the Drop trait or Rust's borrow checker. If you pass a pointer to a Rust-allocated buffer to C, the C library might try to free that memory later, or it might lose track of it entirely, leading to a memory leak.
To handle this, we use the "hand-off" pattern. The goal is to make the C library the "owner" of the data.
The Hand-off Strategy
If you have a Rust-allocated Vec<u8> and you want a C library to take control of it, you must perform two steps:
- Forget the Rust ownership: Use
std::mem::forgetto ensure the Rust side doesn't calldrop()on the memory when theVecgoes out of scope. - Transfer the pointer: Pass the raw pointer to the C function.
fn transfer_to_c(data: Vec<u8>) {
// Get the raw parts of the vector
let (ptr, len, cap) = data.into_raw_parts();
// Pass these to the C library
unsafe {
c_library_take_ownership(ptr, len, cap);
}
// We do NOT call drop(data) or let it fall out of scope
// to reclaim the memory, because C now owns it.
}
Why this matters
In the code above, into_raw_parts() breaks the Vec into its raw components. Crucially, it stops the Vec from cleaning itself up. The C library must be designed to eventually call free() on that exact pointer. If the C library doesn't have a matching "destroy" function, your memory will leak.
Because the C library cannot verify if the memory is still valid, you must be absolutely certain that you are not keeping any references (borrows) to that data in Rust after the hand-off. Once you hand it to C, Rust considers that memory gone forever.
Key Takeaway: To transfer ownership to FFI, you must explicitly disable Rust’s automatic cleanup using std::mem::forget or into_raw_parts and document exactly which C function is responsible for freeing that memory.