4

Example code:

fn main() {
    let mut y = &5; // 1

    println!("{:p}", y);

    {
        let x = &2; // 2
        println!("{:p}", x);
        y = x;
    }

    y = &3; // 3
    println!("{:p}", y);
}

If third assignment contains &3 then code output:

0x558e7da926a0
0x558e7da926a4
0x558e7da926a8

If third assignment contains &2 (same value with second assignment) then code output:

0x558e7da926a0
0x558e7da926a4
0x558e7da926a4

If third assignment contains &5 (same value with first assignment) then code output:

0x558e7da926a0
0x558e7da926a4
0x558e7da926a0

Why does rust not free memory but reuse it if the assignment value is the same or allocate a new block of memory otherwise?

TupleCats
  • 351
  • 3
  • 15
  • Why do you want it to allocate more memory when the same memory can be safely re-used? – Thilo Oct 31 '19 at 08:39
  • @Thilo, I think so but why does Rust do that? I think Rust can free memory after second and third assignments. – TupleCats Oct 31 '19 at 08:47
  • 3
    There is no benefit in free a variable on the stack and then reallocate it with the same value a few instructions later, if there is nothing more important to store there. Works as it should. – Simson Oct 31 '19 at 08:50
  • If these things are allocated from the stack, it would be very wasteful to allocate and free them one by one. Usually, the whole stackframe gets added/removed in one go when functions enter/return. If they are "allocated" as static constants, they don't need dynamic memory management at all. – Thilo Oct 31 '19 at 08:52
  • @Simson, Thanks I understood. – TupleCats Oct 31 '19 at 09:05
  • rule number one of system language, don't assume ~memory~ anything. – Stargateur Oct 31 '19 at 09:08
  • I've heard of half assing, but this is the first I'm learning about third assing. – trent Oct 31 '19 at 11:25
  • Does this answer your question? [Why can I return a reference to a local literal but not a variable?](https://stackoverflow.com/questions/50345139/why-can-i-return-a-reference-to-a-local-literal-but-not-a-variable) – Boiethios Oct 31 '19 at 14:27

2 Answers2

5

Two occurrences of the same literal number are indistinguishable. You cannot expect the address of two literals to be identical, and neither can you expect them to be different.

This allows the compiler (but in fact it is free to do otherwise) to emit one 5 data in the executable code, and have all &5 refer to it. Constants may (see comment) also have a static lifetime, in which case they are not allocated/deallocated during program execution, they always are allocated.

coredump
  • 37,664
  • 5
  • 43
  • 77
  • 2
    Constants *may* be promoted to statics, but in general they may also become temporaries or be compiled away entirely. 5 gets the static promotion treatment here because the code explicitly takes its address; if that weren't so, the compiler would be free to create it in a register or optimize it out of existence, with no 5 appearing in the binary at all. – trent Oct 31 '19 at 11:32
  • 1
    @trentcl I think that it is guaranteed, see https://stackoverflow.com/questions/50345139/why-can-i-return-a-reference-to-a-local-literal-but-not-a-variable – Boiethios Oct 31 '19 at 14:28
  • 1
    @FrenchBoiethios It's guaranteed *because* the address is taken, but constants in general are not subject to static promotion. My earlier comment was to clarify an earlier phrasing of the answer which might have been construed to mean that *all* constants are promoted to statics, which is not true. – trent Oct 31 '19 at 14:49
  • 2
    @trentcl: Actually, I would not be surprised to learn it is NOT guaranteed. Specifically, if the compiler was able to *elide* the address, for example in code such as `let x = &5; println!("{}", 1 + *x);` then I would not expect to find a literal `5` in the data section of the binary, I'd expect to see a `6` directly embedded in the assembly. – Matthieu M. Nov 01 '19 at 14:36
4

There are lots of tricks an optimizing compiler can use to determine if a variable can be assigned a constant value. Your findings are consistent with this, no need to run duplicate code if it is not needed.

Simson
  • 3,373
  • 2
  • 24
  • 38