I've been working with Rust in a constrained embedded environment (on the STM32F303 MCU), and I noticed that some of my functions were allocating an unexpectedly large amount of stack space. In this environment, I do not have an allocator, and need to allocate large, mutable, static data structures on the stack. Eventually, I found that some functions were unexpectedly allocating space on the stack, and causing my memory-constrained stack to overflow.
I am looking to understand how much memory needs to be allocated on the stack for the following mutate
function.
I've been searching for answers to this problem on this site, but none seem to give an answer for this more general problem.
I understand that for this code block below I can look at the LLVM/assembly to see where the allocations are made, but I'm trying to understand how to predict when stack allocations are made for a general class of problems- independent of compiler options and the optimizer.
The following problem is a toy example which mimics the pattern I'm using (and having issues with) in my embedded Rust program.
Question: How much memory does mutate
below need to allocate on the stack?
struct Parent {
data: Option<[u32; 1024]>,
}
impl Parent {
pub fn new() -> Self {
Parent { data: None }
}
// Ideally, this function should allocate negligible memory on the stack
pub fn mutate(&mut self) {
let arr = [0u32; 1024];
self.data = Some(arr);
for i in 0..self.data.unwrap().len() {
self.data.unwrap()[i] = i as u32;
}
}
}
fn main() {
let mut it = Parent::new();
it.mutate();
}
Considerations
- Other posts seem to suggest this behavior is up to the optimizer. If this is the case, is there a way I can rewrite the code above so that each function's stack allocation size is obvious to the reader of the code?
- Does the let keyword (first line in the
mutate
function) have any affect on whether the large array is allocated on the stack? - I am sure I could dip into
unsafe
rust to ensure this function doesn't need to make any allocations/memcpys (like I could in C). Is there a better way to do this without usingunsafe
?
Thanks in advance for any help on this issue.