Function sgx_tstd::mem::forget 1.0.0[−][src]
pub fn forget<T>(t: T)
Leaks a value: takes ownership and "forgets" about the value without running its destructor.
Any resources the value manages, such as heap memory or a file handle, will linger forever in an unreachable state.
If you want to dispose of a value properly, running its destructor, see
mem::drop
.
Safety
forget
is not marked as unsafe
, because Rust's safety guarantees
do not include a guarantee that destructors will always run. For example,
a program can create a reference cycle using Rc
, or call
process::exit
to exit without running destructors. Thus, allowing
mem::forget
from safe code does not fundamentally change Rust's safety
guarantees.
That said, leaking resources such as memory or I/O objects is usually undesirable,
so forget
is only recommended for specialized use cases like those shown below.
Because forgetting a value is allowed, any unsafe
code you write must
allow for this possibility. You cannot return a value and expect that the
caller will necessarily run the value's destructor.
Examples
Leak some heap memory by never deallocating it:
use std::mem; let heap_memory = Box::new(3); mem::forget(heap_memory);
Leak an I/O object, never closing the file:
use std::mem; use std::fs::File; let file = File::open("foo.txt").unwrap(); mem::forget(file);
The practical use cases for forget
are rather specialized and mainly come
up in unsafe or FFI code.
Use case 1
You have created an uninitialized value using mem::uninitialized
.
You must either initialize or forget
it on every computation path before
Rust drops it automatically, like at the end of a scope or after a panic.
Running the destructor on an uninitialized value would be undefined behavior.
use std::mem; use std::ptr; unsafe { let mut uninit_vec: Vec<u32> = mem::uninitialized(); if some_condition { // Initialize the variable. ptr::write(&mut uninit_vec, Vec::new()); } else { // Forget the uninitialized value so its destructor doesn't run. mem::forget(uninit_vec); } }
Use case 2
You have duplicated the bytes making up a value, without doing a proper
Clone
. You need the value's destructor to run only once,
because a double free
is undefined behavior.
An example is a possible implementation of mem::swap
:
use std::mem; use std::ptr; fn swap<T>(x: &mut T, y: &mut T) { unsafe { // Give ourselves some scratch space to work with let mut t: T = mem::uninitialized(); // Perform the swap, `&mut` pointers never alias ptr::copy_nonoverlapping(&*x, &mut t, 1); ptr::copy_nonoverlapping(&*y, x, 1); ptr::copy_nonoverlapping(&t, y, 1); // y and t now point to the same thing, but we need to completely // forget `t` because we do not want to run the destructor for `T` // on its value, which is still owned somewhere outside this function. mem::forget(t); } }
Use case 3
You are transferring ownership across a FFI boundary to code written in
another language. You need to forget
the value on the Rust side because Rust
code is no longer responsible for it.
use std::mem; extern "C" { fn my_c_function(x: *const u32); } let x: Box<u32> = Box::new(3); // Transfer ownership into C code. unsafe { my_c_function(&*x); } mem::forget(x);
In this case, C code must call back into Rust to free the object. Calling C's free
function on a Box
is not safe! Also, Box
provides an into_raw
method which is the preferred way to do this in practice.