'Why doesn't heap memory get dropped when a value is moved?
The Rust Programming Language says:
when a variable goes out of scope, Rust automatically calls the drop function and cleans up the heap memory for that variable.
Let's look at the 2 cases.
fn dangle() -> &String { // dangle returns a reference to a String
let s = String::from("hello"); // s is a new String
&s // we return a reference to the String, s
}
fn no_dangle() -> String {
let s = String::from("hello");
s
}
In the first example, when s goes out of scope, s is said to be deallocated and dropped. This means that s on the stack is removed and the heap memory is deallocated/cleaned.
In the second example, s is moved. I understand that, but why doesn't the heap memory get dropped? What's the rule here that the heap memory stays alive? s went out of the scope, so heap should also be destroyed.
Solution 1:[1]
In the second example, s is moved. I understand that, but why doesn't the heap memory get dropped? What's the rule here that the heap memory stays alive? s went out of the scope, so heap should also be destroyed.
It sounds like your intuition is that of C++: in C++, moves are "non-destructive" and all variables are destroyed (their destructor is called) at end of scope.
But rust follows a very different logic of destructive moves: when a variable is moved from, it is considered dead, and so there is no way to "kill" them again (for what is dead may never die), and thus dropping them doesn't make sense. So
fn f() -> String {
let s = String::from("hello");
s // implicit return moves the value
// s is dead here, so it doesn't get dropped
}
fn g() -> () {
let s = String::from("hello");
// move value into a function
Box::leak(Box::new(s));
// s is dead here, so it doesn't get dropped
}
fn h() -> () {
let s = String::from("hello");
// borrow value
println!("{}", s);
// s is *live* here, it needs to be dropped
}
Solution 2:[2]
Refer to the book, the compiler remembers which values are moved already, and does not call drop on them. This is an example, the drop function would be called only once, not for moved value s:
struct MyString {
a: String,
}
impl Drop for MyString {
fn drop(&mut self) {
println!("Dropping My String!");
}
}
fn no_dangle() -> MyString {
let s = MyString{a: String::from("hello")};
println!("Show {1}: {0}, {1} drops after this line.", s.a, "s");
println!("Inside no_dangle...");
s
}
fn main() {
let ss = no_dangle();
println!("Outside no_dangle...");
println!("Show {1}: {0}, {1} drops after this line.", ss.a, "ss");
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Masklinn |
| Solution 2 |
