Stack usage of arrays

I'm trying to understand stack usage of some embedded rust code. Essentially, I have an array of fixed size on the stack, and I'm looking to understand the according placement and memory usage of the array on stack (I have read the embedonomicon, which was amazing!)

Complete code

  #![no_main]
#![no_std]

use panic_reset as _;

use cortex_m_rt::{entry, exception, ExceptionFrame};
use nrf52833_hal;

const SZ: usize = 4096;

#[entry]
fn main() -> ! {
    let mut device = [0; SZ];
    loop {}
}

#[exception]
fn DefaultHandler(_: i16) {}

If I disable all optimizations and compile and look at the disassembled code, what I'm seeing is that the the stack pointer is moved 4x size of the array on the stack. This seems to be the case both on x86_64 and ARM cortex-m architectures. Snippet from assembly:

00000162 <_ZN11stack_debug18__cortex_m_rt_main17he1fc75bceb91d78aE>:
 162:	push	{r4, r5, r7, lr}
 164:	add	r7, sp, #8
 166:	sub.w	sp, sp, #16384	; 0x4000 <-- 4x 4096
 16a:	mov	r0, sp
 16c:	mov.w	r1, #16384	; 0x4000
 170:	bl	6d0 <__aeabi_memclr4>
 174:	b.n	176 <_ZN11stack_debug18__cortex_m_rt_main17he1fc75bceb91d78aE+0x14>
 176:	b.n	176 <_ZN11stack_debug18__cortex_m_rt_main17he1fc75bceb91d78aE+0x14>

Is this expected behavior? If so, why is it expected?

My guess is that it's allocating 4096 4-byte integers. Does it change if you specify the type explicitly?

let mut device: [u8; SZ] = [0; SZ];
1 Like

You are right, this was the case. I need to go back to my original problem again from which I made this example, but this clarifies what I've seen when debugging my original code. Thanks for the quick reply!

Or:

let mut device = [0u8; SZ];

If Rust can't figure out the type of an integer literal, it assumes it's i32, so the original code ends up being equivalent to:

let mut device = [0i32; SZ];
6 Likes