In C/C++ and other low-level languages, the developer must explicitly manage the placement of data in memory: on the stack (automatic variables) or in the heap (allocation via malloc/new). These languages often encounter errors with memory leaks, double free, or the use of uninitialized or already deallocated memory. Rust takes on strict memory control using a ownership system, without a garbage collector.
Automatic memory management via the stack is convenient but limited by size (stack depth). Allocation in the heap requires explicit resource management, which is dangerous: one can forget to free memory or violate the lifetimes of pointers. A garbage collector is not always a solution (resource overhead, unpredictable pauses). Memory management errors lead to crashes and vulnerabilities.
In Rust, the stack and heap differ through automatic management: all values are placed on the stack by default, while dynamically sized or long-lived objects use the heap through smart pointers (e.g., Box<T>, Vec<T>). The ownership and borrowing system ensures that after ownership transfer or the end of a resource's lifetime, resources will be freed automatically. This provides guaranteed safety at compile time and eliminates unnecessary pauses from a garbage collector.
Code example:
fn main() { let a = 42; // stack allocation let b = Box::new(42); // heap allocation let mut v = Vec::new(); v.push(1); v.push(2); // array data in heap }
Key features:
Can memory on the stack be manually freed (dropped)?
No. The release of stack-allocated variables occurs automatically when going out of scope; manually dropping is useless and even inappropriate for stack pointers.
Does moving (move) implicate transfer to the heap?
No. Moving a variable between owners does not necessarily move it to the heap; only the ownership changes.
Does using Box<T> guarantee that T is always in the heap?
Yes, Box<T> indeed allocates T on the heap, however, ownership and lifetime are still strictly controlled.
In the project, global vectors (Vec<T>) are used with manual cleaning implemented via mem::forget or drop, sometimes leaving dangling pointers to deallocated memory.
Pros:
Cons:
Objects are explicitly allocated via Box, data transfer occurs by ownership rules, smart pointers are used for collections, and references to stack variables are not returned.
Pros:
Cons: