Memory allocation in rust

Hi everyone,

I had a very basic question regarding rust memory allocation.
In the following code, when and where(stack or heap) will the memory be allocated for the struct.

struct User {
    name: i32,
    admin: bool,
}

impl User {
    pub fn new(name: i32) -> Self {
        Self {
            name,
            admin: false,
        }
    }
}

fn main() {
    eprintln!("Allocate the new struct");
    **let p = User::new(23);** //is this where the allocation will happen
    eprintln!("New struct is now allocated");
    // eprintln!("{}",p.name)
}

At what point of time will the memory of the highlighted code be implemented. Will it be statically(at compile time) allocated at the start of the program or will it be dynamically(at runtime) allocated(using malloc) when the call to new is made?

Also, will this memory be allocated in stack or heap?

If we talk about the same memory allocation in C, we know that any struct allocation will require a runtime call to malloc for memory to be allocated in the heap. So how does rust handle this type of allocation?

Please correct me if I am wrong at any point :slight_smile:

new in Rust is not like new in C++, Java, C#, etc. It's just a regular function name. So there is no heap allocation in constructing the User value.

All the allocation here is done on the stack. As to precisely when it happens depends on the compiler and optimiser. For example, the compiler might (rightly) realise that you never actually use p, so it never allocates it at all. Or, if you only use part of it, it might just directly store that field and ignore the rest. Or maybe not.

If it's on the stack, the space is probably reserved at the start of the function... assuming there isn't some sort of optimisation pass at some point that moves it to conserve stack space.

Heck, if you're lucky, LLVM might turn a heap allocation into a stack allocation.

So if you turn optimisations off, then p will probably be allocated dynamically on the stack in this particular instance.

6 Likes

This is not the case.

One can declare a struct at global scope in C. In which case memory is reserved for it at compile time.

Or move that declaration into a function, a local variable, and it will be allocated space on the stack, dynamically at run time. Of course it disappears when the function returns.

Or one can use malloc to allocate some memory on the heap. The allocated memory is just a bunch of bytes so one then has to access it as the struct one wants via a pointer and type cast.

In your Rust example the User will be given space on the stack.

As you never actually use the User struct it is likely it never exists in the compiled code when optimisations are on (release build).

6 Likes

As a follow-up, if we comment out the eprintln! lines and feed the code to Godbolt, we get this assembly:

example::User::new:
        mov     dword ptr [rsp - 8], edi
        mov     byte ptr [rsp - 4], 0
        mov     eax, dword ptr [rsp - 8]
        mov     dl, byte ptr [rsp - 4]
        ret

example::main:
        push    rax
        mov     edi, 23
        call    example::User::new
        pop     rax
        ret

If you can't read this (my amd64 is very sketchy, so take this with a grain of salt): there is no allocation at all. Instead, the contents of User are being returned in a pair of registers (eax, and dl).

1 Like

This is false. You can just declare stack-allocated (local) variables of a struct type in C. This has nothing to do with whether something is a struct. A struct doesn't inherently need heap allocation any more than any other type.

C never allocates on the heap implicitly, and neither does Rust.

5 Likes

ohk.. understood. Thanks for the info.

Yes, Got this point. Thanks for the clarification.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.