Function sgx_tstd::mem::forget1.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.