Does Rust save the memory of rewritten variables?

In the Rust book, I saw that you can define two different variables with the same name:

let hello = "Hello"; let hello = "Goodbye"; println!("My variable hello contains: {}", hello); 

This produces:

 My variable hello contains: Goodbye 

What happens to the first greeting? Is he freed? How can I access it?

I know that it would be bad to call two variables the same, but if this happens by accident, because I declare it 100 lines below, it can be a real pain.

+7
memory-management rust
source share
2 answers

Rust does not have a garbage collector .

Does Rust save the memory of rewritten variables?

Yes, otherwise it would be a memory leak, which would be a rather awful constructive solution.

what happens with the first greeting

It is shaded .

Nothing "special" happens to the data referenced by the variable, except for the fact that you can no longer get it. It still crashes when the variable goes outside the scope.

Here is the code that is output when each variable is deleted:

 struct Noisy; impl Drop for Noisy { fn drop(&mut self) { println!("Dropped") } } fn main() { println!("0"); let thing = Noisy; println!("1"); let thing = Noisy; println!("2"); } 
 0 1 2 Dropped Dropped 

I know that it would be bad to call two variables the same

This is not "bad", it is a design decision. I would say that using a shadow image is a bad idea:

 let x = "Anna"; println!("User name is {}", x); let x = 42; println!("The tax rate is {}", x); 

Using a similar shadow is reasonable for me:

 let name = String::from(" Vivian "); let name = name.trim(); println!("User name is {}", x); 

See also:

  • Why do I need to double-check / shade when I can bind a variable to a variable?

but if this happens by accident, because I declare that it is 100 lines below, it can be a real pain.

You do not have functions that are so great that you "accidentally" do something. This is applicable in any programming language.

Is there a way to clear memory manually?

You can call drop :

 println!("0"); let thing = Noisy; drop(thing); println!("1"); let thing = Noisy; println!("2"); 
 0 Dropped 1 2 Dropped 

However, since oli_obk - ker indicates , the memory stack taken by this variable will not be freed until the function exits, but only the resources received by the variable.

All discussions of the drop require a display of a (very complex) implementation:

 fn drop<T>(_: T) {} 

What if I declare a variable in a global scope outside of other functions?

Global variables are never freed, if you can even create them for starters.

+9
source share

There is a difference between shading and rewriting variables when it comes to sort order.

All local variables are usually deleted when they exit the scope in the reverse order of declaration (see the "Rust Programming Language" section on the Drop chapter ). This includes shaded variables. It's easy to verify this by wrapping the value in a simple wrapper structure that prints something when it (the wrapper) is discarded (just before the value itself is omitted):

 use std::fmt::Debug; struct NoisyDrop<T: Debug>(T); impl<T: Debug> Drop for NoisyDrop<T> { fn drop(&mut self) { println!("dropping {:?}", self.0); } } fn main() { let hello = NoisyDrop("Hello"); let hello = NoisyDrop("Goodbye"); println!("My variable hello contains: {}", hello.0); } 

prints the following ( playground ):

 My variable hello contains: Goodbye dropping "Goodbye" dropping "Hello" 

This is because the new let binding in the scope does not overwrite the previous binding, so as if you wrote

  let hello1 = NoisyDrop("Hello"); let hello2 = NoisyDrop("Goodbye"); println!("My variable hello contains: {}", hello2.0); 

Please note that this behavior is different from the following, very similar in appearance code ( playground ):

 fn main() { let mut hello = NoisyDrop("Hello"); hello = NoisyDrop("Goodbye"); println!("My variable hello contains: {}", hello.0); } 

which not only discards them in the reverse order, but also punishes the first value before printing the message! This is because when you assign a variable (instead of shading it with a new one), the original value first falls before the new value is moved.

I started by saying that local variables are "usually" discarded when they go beyond. Since you can move values ​​to and from variables, analysis of the calculations when you need to drop variables can sometimes not be performed before execution. In such cases, the compiler actually inserts the tracking code “live” and discards these values ​​if necessary , so you cannot accidentally cause leaks by overwriting the value. (However, you can still safely leak memory by calling mem::forget , or by creating an Rc loop with internal mutability.)

+5
source share

All Articles