Why are the pointers same?


struct Person<T>{
    _age: Option<T>,
}

impl<T> Person<T>{
    fn raw(){
        (0..4).for_each(|_|{
            let mut p = Person{
                _age: None,
            };
            let ptr = &mut p as *mut Person<T> as usize;
            println!("{}", ptr);
        });
        
    }
}


fn main(){
    Person::<u32>::raw();
}

when I print the ptr, they are same, why?

In general you shouldn't make assumptions about whether local variables would have the same memory address across function calls. In this case, where the closure is simple and the iterator has no reason to be doing complicated things between calls to the closure it makes sense that the address happens to be stable though.

p is a just a variable on the stack, so it's address depends on the stack state when the closure is called and not the specific value passed to the closure.

3 Likes

If so, How do I get the raw pointer or address of every Person?

What do you mean by "address of every Person" here? You definitely got the address of the locations where they were temporarily stored, but you also definitely want something else.

5 Likes

Got it, I have changed the method, now they are different.

fn raw(){
        let mut ps = Vec::new();
        for i in 0..4{
            let mut p = Person{
                _age: Some(i),
            };
            let ptr = &mut p as *mut Person as usize;
            ps.push(p);
            println!("{}", ptr);
        }
        println!("{:?}", ps);
        for p in ps.iter(){
            let ptr = p as *const Person as usize;
            println!("{}", ptr);
        }
    }

Thanks a lot!

I think this is more better:

fn raw(){
        let mut ps = Vec::new();
        for i in 0..4{
            let p = Arc::new(Person{
                _age: Some(i),
            });
            let ptr = Arc::into_raw(p) as usize;
            ps.push(ptr);
        }
        println!("{:?}", ps);
    }

Unlike garbage-collected languages, Rust doesn't put objects on the heap automatically, so they don't get a stable address.

Even when objects have an address, it can change at any time you assign or pass the value to a function. Addresses can be recycled and different objects can end up having the same address (but not at the same time).

Thanks to optimizations, the objects may not even have any address at all! The _age could have been put in a register, or the whole Person object could have been optimized out entirely and never exist in the first place.

6 Likes

Different objects can actually have the same address at the same time too, when

  • One is part of another (e.g. the first field of a struct, recursively)
  • ZSTs (Zero-Sized Types) are involved
5 Likes