fn test_stack_array() -> [u8; 512*1024] {
let stack_top = 1;
let array = [0; 512*1024];
let stack_bottom = 1;
println!("addr of (top, bottom) of stack is (0x{:x}, 0x{:x}), addr of (array[0], array[-1]) is (0x{:x}, 0x{:x})",
&stack_top as *const i32 as usize, &stack_bottom as *const i32 as usize,
&array[0] as *const u8 as usize, &array[512*1024-1] as *const u8 as usize);
array
}
....
let a = test_stack_array();
println!("access array a[]:{}, addr of array out of function is : 0x{:x}", a[10], &a as *const u8 as usize);
.....
the result:
addr of (top, bottom) of stack is (0x19f610, 0x19f614), addr of (array[0], array[-1]) is (0x19f760, 0x21f75f)
access array a[]:0, addr of array out of function is : 0x19f760
returns the array allocated in function(at the stack space) , which means that space will not be freed. so does it mean the stack will exist many leaks and be managed like in heap? I think managing stack is more efficient than managing heap, is it correct?
Stack memory management is simpler and more efficient than heap memory management, yes, but that’s not the whole picture. When a Rust function returns, it moves (copies) the return value into the caller’s stack frame, which is not necessary if the object is stored on the heap. So there’s a tradeoff to be made here:
Heap: Expensive allocations and cheap moves (ownership transfers)
Stack: Cheap allocations and expensive moves
As values get larger, the move cost starts to dominate the allocation cost and the heap becomes preferable.
In this case, it looks like you've run into return value optimization. Rust can see that you create the local variable just to return it from the function, so it is created in the caller's stack, not in the callee's.
I'd just like to point out that while yes, "Heap memory being cheap to move and Stack memory being expensive to move", is the mental model you should probably use, once optimizations kick in it can become irrelevant. See
That does not sound quite right to me. When it comes down to actually copying bytes around it all boils down to memcpy() or some such that does not care where the memory it is copying is.
The trade off is the overheads of calling a memcpy, which gets bigger with data size, vs a cheap pointer move. Size is the key. Not stack or heap location.
Of course I would expect actually creating and destroying things on the stack to be a lot quicker than heap allocation/deallocation. So that plays into the equation as well.