Does the ownership means owning the value or the memory?

fn main(){
    let mut s  = String::from("hello");
    println!("The memory address of s is: {:p}", &s as *const String);
    s = String::from("world");
    println!("The momory address os s is: {:p}", &s as *const String);
}

the result in playground is

The memory address of s is: 0x7ffc812c04c0
The momory address os s is: 0x7ffc812c04c0

First, I'm just curious about how Rust deal with the old value String "hello"
Because the doc says

  • Each value in Rust has an owner.

So I assume what happened here is new memory is allocated on the heap and given the value "world".
Then s own the value "world" which results in the dropping of "hello"

But it seems there is no move happen.
as a result, it's more like replacing, the String "world" replace the "hello". They have the save memory

So I'm a little bit confuse here.
Thanks for clearing up!

In general ownership has two aspects:

  • The right to move the value anywhere in memory, and
  • The responsibility to drop the value when it is no longer available.

For a type like String, there are two chunks of memory to consider:

  • The string value itself, which is a (pointer, length) pair. In your example, this is stored on the stack in a fixed location; this is the location that you're printing
  • The heap buffer where the actual characters are stored, which you can get the address of via String::as_str()

The line s = String::from("world") first drops the original string value, which deallocates the heap buffer containing "hello". It then stores a pointer, etc. to a new heap buffer that contains "world" into the same stack location the old pointer was stored in.

At the end of main, the contents of the s variable are dropped just before the stack frame goes away, deallocating the buffer containing "world".

4 Likes

oh shxxxt . I got the wrong address...
but String::as_str() is extracting a string slice containing the entire String other than getting the address.
you must be referring to as_ptr()

I'm not sure exactly what you meant by "extracting", but refer to this diagram for the difference between &String and &str. as_ptr give a raw pointer to the same address as the &str (the "Pointer" of &str and String in the diagram).

1 Like

Switch to this instead https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=566f1c5a160276c29d9c7639d3c49a5a

fn main(){
    let mut s  = String::from("hello");
    println!("The memory address of s is: {:p}", &s as *const String);
    println!("The memory address of *s is: {:p}", &*s as *const str);
    s = String::from("world");
    println!("The memory address of s is: {:p}", &s as *const String);
    println!("The memory address of *s is: {:p}", &*s as *const str);
}

And you'll see something more like what it sounds like you were expecting:

The memory address of s is: 0x7ffe36a7efe0
The memory address of *s is: 0x55adbfeab9d0
The memory address of s is: 0x7ffe36a7efe0
The memory address of *s is: 0x55adbfeab9f0

The local binding is at the same address both times, but the UTF-8 text inside the string is at different places.


Of course, if instead of making a fresh String (then moving it over the old one) you ask to put the string literal into the existing value,

fn main(){
    let mut s  = String::from("hello");
    println!("The memory address of s is: {:p}", &s as *const String);
    println!("The memory address of *s is: {:p}", &*s as *const str);
    "world".clone_into(&mut s); // <-- HERE
    println!("The memory address of s is: {:p}", &s as *const String);
    println!("The memory address of *s is: {:p}", &*s as *const str);
}

you'll see the same allocation being re-used again.

6 Likes

You can use {:p} formatter to print the target address of &T references, including &str, so yet .as_str() does work.

fn main(){
    let mut s  = String::from("hello");
    println!("The memory address of s is: {:p}", s.as_str());
    s = String::from("world");
    println!("The momory address os s is: {:p}", s.as_str());
}

Rust Playground

The memory address of s is: 0x564032e779d0
The momory address os s is: 0x564032e779f0
1 Like

Emm...
"world".clone_into(&mut s); change the value inside s.
so It also make sense that ownership means owning the memory where store the value. Maybe more precise, right?