48

Is there any way of causing a memory leak in Rust? I know that even in garbage-collected languages like JavaScript there are edge-cases where memory will be leaked, are there any such cases in Rust?

2
  • 3
    I created an event listener leak just now in rust, and found this thread when searching for approaches to "prevent memory leak in rust". Commented Sep 27, 2019 at 4:32
  • I was actually looking for a way of intentionally leaking memory in kernel development. Creating page tables means that they need to stay longer than the usual lifetime of the value would be, maybe even forever.
    – xdevs23
    Commented Apr 30, 2023 at 13:46

3 Answers 3

64

Yes, leaking memory in Rust is as easy as calling the std::mem::forget function.

You can also leak memory if you create a cycle of shared references:

A cycle between Rc pointers will never be deallocated. For this reason, Weak is used to break cycles. For example, a tree could have strong Rc pointers from parent nodes to children, and Weak pointers from children back to their parents.

You can also use Box::leak to create a static reference, or Box::into_raw in an FFI situation.


Actually, in a system programming language, you need to be able to create a memory leak, otherwise, for example in an FFI case, your resource would be freed after being sent for use in another language.


All those examples show that a memory leak does not offend the memory safety guaranteed by Rust. However, it is safe to assume that in Rust, you do not have any memory leak, unless you do a very specific thing.

Also, note that if you adopt a loose definition of the memory leak, there are infinite ways to create one, for example, by adding some data in a container without releasing the unused one.

9
  • 2
    You might've forgotten about Box::leak and Box::into_raw which are pretty common in ffi situations for passing around states. Commented Apr 7, 2019 at 15:26
  • 12
    For the curious, a bit of online searching reveals that "FFI" stands for "Foreign Function Interface". :) (Not obvious to Rust beginners.)
    – Teekin
    Commented Jun 27, 2020 at 15:39
  • I wouldn't say that circular references and stuff like that are “quite exotic”. Unless you're working on simple examples, you will probably run into something equaly exotic pretty soon. Commented Dec 15, 2020 at 7:50
  • 1
    I guess I think of it as a memory leak since in the garbage-collected languages I mostly work with, it's the only way you can accidentally use up available memory with unused data, and since it's basically the same as accidentally keeping around a reference to a smart pointer
    – Andy
    Commented Jan 27, 2021 at 22:23
  • 3
    Maybe the term memory leak originally meant forgetting to call free, but that's really only one part of the larger picture of how programs accidentally run out of memory. Forgetting to call free directly and forgetting to do something that would indirectly trigger a call to free have the same consequences
    – Andy
    Commented Jan 27, 2021 at 22:25
22

From the book

Rust’s memory safety guarantees make it difficult, but not impossible, to accidentally create memory that is never cleaned up (known as a memory leak). Preventing memory leaks entirely is not one of Rust’s guarantees in the same way that disallowing data races at compile time is, meaning memory leaks are memory safe in Rust.

So the answer is yes. You can have memory leaks in your code and rust compiler won't complain about it.

2
use std::rc::Rc;
use std::cell::{RefCell};

Rc creates a smart pointer to count the references. Similar to how garbage collector counts references. Since Rc hold shared reference it is always immutable

Refcell is also a smart pointer that represents single ownership over the data but the ownership rule is checked at run time not at compile time. with Refcell we can get a mutable reference of an immutable variable.

let x=32;
let x1=&mut x;

Normally, this is not allowed because x is immutable and we are getting a mutable reference to it. But with Refcell we get this power.

Together, wrapping Refcell with Rc we can create shared reference which can mutate the data.

After this intro, this code will create memory leakage:

use std::rc::Rc;
use std::cell::{RefCell};

#[derive(Debug)]
struct Node{
    next:Option<Rc<RefCell<Node>>>,
}
fn main(){
    let a=Rc::new(RefCell::new(Node{next:None}));
    let b=Rc::new(RefCell::new(Node{next:Some(Rc::clone(&a))}));
    let c=Rc::new(RefCell::new(Node{next:Some(Rc::clone(&b))}));
    // we do not have any cycles so far

    // after this line we have cycle. a-> b -> c -> a
    (*a).borrow_mut().next=Some(Rc::clone(&c));
    println!("a {:?}",a);
}

when you print "a", a points to b which points to c which points a again, so will see this in the terminal:

enter image description here

You can read here Reference Cycles Can Leak Memory

Not the answer you're looking for? Browse other questions tagged or ask your own question.