You have a number of issues here, none of which relate to copying a pointer.
I see what you're trying to do, but you're seeing 'undefined behavior' in action, not a failure to copy the pointer value.
First of all, this:
temp_b.next.unwrap()
Unwrap does not leave the object behind; it consumes it. Every iteration through, you will be setting the value of next
to nothing as you call unwrap
.
Secondly, on the first iteration through your loop, you convert the original pointer into a box:
let mut p: *mut ListNode = self as *mut ListNode;
// ... p is not reassigned before calling the next statement
Box::from_raw(p);
As a result, you're dropping (free'ing) the root object a when you consume temp_b.
This won't immediately trigger a crash, but it means you've now effectively corrupted the stack. Everything past this point is undefined behavior.
Look at the output when you trace your actual pointer values:
#[derive(Debug)]
struct ListNode {
val: String,
next: Option<Box<ListNode>>,
}
impl ListNode {
fn new(i: &str) -> Self {
ListNode { val: format!("{:?}", i), next: None }
}
fn add_l(&mut self, l: &Vec<&str>) {
let mut p: *mut ListNode = self as *mut ListNode;
println!("self -> {:?}", self as *mut ListNode);
for i in l {
unsafe {
(*p).next = Some(Box::new(ListNode::new(*i)));
let temp_b = Box::from_raw(p);
println!("{:?} -> {:?}", p, temp_b);
p = Box::into_raw(temp_b.next.unwrap());
println!("next p -> {:?}", p);
};
}
println!("self -> {:?}", self as *mut ListNode);
}
}
fn main() {
let mut a = ListNode::new("1");
a.add_l(&vec!["2", "3", "4", "5"]);
println!("self -> {:?}", &mut a as *mut ListNode);
println!("{:?}", a);
}
...
self -> 0x7ffdc10a90f0
0x7ffdc10a90f0 -> ListNode { val: "\"1\"", next: Some(ListNode { val: "\"2\"", next: None }) }
next p -> 0x7fdde801f060
0x7fdde801f060 -> ListNode { val: "\"2\"", next: Some(ListNode { val: "\"3\"", next: None }) }
next p -> 0x7ffdc10a90f0
0x7ffdc10a90f0 -> ListNode { val: "\"3\"", next: Some(ListNode { val: "\"4\"", next: None }) }
next p -> 0x7fdde801f060
0x7fdde801f060 -> ListNode { val: "\"4\"", next: Some(ListNode { val: "\"5\"", next: None }) }
next p -> 0x7ffdc10a90f0 <---- Whhhaaaat! You've been reallocated!
self -> 0x7ffdc10a90f0
self -> 0x7ffdc10a90f0
ListNode { val: "\"5\"", next: None }
So... this is why using unsafe
is unsafe.
You can't do what you want to do without using raw pointers all the way; I recommend you look at Rc
for what you're trying to do.