Unmatched pointer value of a string when ownership is passed on

Coming from C++, thought that understanding of pointers would be an easy one. Trying to understand the ownership concept using String type with the following code snippet. Irrespective of the deliberate ownership change from "s" -> "w" the pointer value has to be pointing to the memory address of "H". Accordingly, the as_prt() method is returning the raw pointer to "H" but the same is not true when s_ptr and w_ptr are used. I'm assuming that the s_ptr and w_ptr are the pointers of "s" and "w" strings data (pointer, length, and capacity) respectively located on the stack. Correct me if I'm wrong, else please let me know why the pointers (s_ptr and w_ptr) are different.

fn main(){

let s = String::from("Hello, world!");

let s_ptr:&String = &s;

println!("Pointer of {} is {:p}", s, s_ptr);

println!("Pointer of {} is {:p}", s, s.as_ptr());

println!("Size = {}", get_string_length(s));

}

fn get_string_length(w: String) -> usize{

let w_ptr:&String = &w;

println!("Pointer of {} is {:p}", w, w_ptr);

println!("Pointer of {} is {:p}", w, w.as_ptr());

w.len()

}

As far as I understand:

s is a String. A String object has at least a pointer to some bytes that are the actual string "Hello, world!" and a length.

The object s itself lives on the stack as a local variable.

s points to the bytes "Hello, world!" which is in some static literal space.

Meanwhile:

s_ptr is a reference to that s object on the stack.

Hence they are not pointing at the same things. One points at a string of bytes, the other points to the string object on the stack.

How am I doing?

1 Like
println!("Size = {}", get_string_length(s));

Here, the local variable s is moved into the w parameter of get_string_length; that is, a new variable is created. However, moving steals content from the source String; the same heap memory gets pointed to by the new variable. Since you are from C++, this might help: (I used std::vector rather than std::string, because the latter has small string optimization)

#include <cstddef>
#include <iostream>
#include <utility>
#include <vector>

std::size_t get_length(std::vector<int> w) {
    auto p = &w;

    std::cout << p << '\n';
    std::cout << w.data() << '\n';

    return w.size();
}

int main() {
    std::vector<int> s{1, 2, 3};
    auto p = &s;

    std::cout << p << '\n';
    std::cout << s.data() << '\n';

    get_length(std::move(s));
}

The output is basically the same:

0x7ffc5ce69660
0x1b59e70
0x7ffc5ce69680
0x1b59e70

(godbolt)


By the way, you can surround your code by three backticks to format it in the correct font.

1 Like

If the variable s is defined as, for instance, let s = String::from("foo"); then &s is the address of the variable s itself, i.e. it points to s, whereas s.as_ptr() points to the beginning of the underlying, dynamically-allocated buffer of bytes. These are of course different addresses — Strings do not store their content inline.

1 Like

@ZiCog, @L.F
Thank you

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.