- Speed: The stack offers very fast allocation and deallocation due to its fixed size managed by the compiler.
- Lifetime: Stack data is automatically deallocated when it goes out of scope (typically at the end of a function).
- Use Cases: Stack allocation is ideal for fixed-size data types known at compile time, such as integers, floats, booleans, and small arrays.
- Dynamic Size: Data stored on the heap can grow or shrink at runtime, making it suitable for collections like vectors, strings, and dynamically sized structures.
- Explicit Management: Programmers are responsible for allocating and deallocating memory on the heap. Memory leaks can occur if not managed properly.
- Ownership Rules: Rust's ownership system dictates how data is allocated and deallocated on the heap, preventing memory leaks.
fn main() {
stack_fn(); // Call the function that uses stack memory
heap_fn(); // Call the function that uses heap memory
update_string(); // Call the function that changes size of variable at runtime
}
fn stack_fn() {
// Declare a few integers on the stack
let a = 10;
let b = 20;
let c = a + b;
println!("Stack function: The sum of {} and {} is {}", a, b, c);
}
fn heap_fn() {
// Create a string, which is allocated on the heap
let s1 = String::from("Hello");
let s2 = String::from("World");
let combined = format!("{} {}", s1, s2);
println!("Heap function: Combined string is '{}'", combined);
}
fn update_string() {
// Start with a base string on the heap
let mut s = String::from("Initial string");
println!("Before update: {}", s);
// Append some text to the string
s.push_str(" and some additional text");
println!("After update: {}", s);
}| Data Type | Allocation | Description |
|---|---|---|
| Numbers (integers, floats) | Stack | Primitive data types with fixed size known at compile time. |
| Booleans | Stack | true or false values requiring minimal space. |
| Fixed-size Arrays | Stack | Arrays with a predetermined size declared during compilation. |
| Strings | Heap | Dynamically sized collections of characters that can grow or shrink at runtime. |
| Vectors | Heap | Resizable collections of elements, similar to arrays but offering dynamic resizing capabilities. |
When working with strings, an interesting aspect to consider is memory management during updates. Since strings are heap-allocated, modifying them (e.g., concatenating) might involve:
- Reallocation: If the existing string doesn't have enough space to accommodate the update, Rust might need to allocate a new, larger block of memory on the heap for the modified string. This involves copying the original string's content and appending the new data.
- In-place Modification: If the existing string has sufficient capacity for the update, Rust might be able to modify the string data directly in its allocated heap memory, avoiding reallocation.
Rust's ownership system ensures that the original string's memory is properly released when it's no longer needed, preventing memory leaks.
Understanding stack and heap allocation in Rust is crucial for efficient memory usage. Utilize the stack for fast, fixed-size data and the heap for dynamic data structures while adhering to Rust's ownership principles. This approach ensures your programs are both safe and performant.
-
When the program is executed, a stack frame is initialized and all the variables used are placed into the frame
-
When another function is called, another stack frame is created and all the variables used are placed into the frame
-
As soon as the function's execution completes, it's stack frame is flushed out of the memory to empty the space.



