Storing value of a pointer in another pointer in R

2019-05-31 03:47发布

What is the best way to store a pointer as a value of another pointer?

I have a variable ptr that is of type *mut u8. How do I store the address that the ptr points to as the value of another pointer t that is also of type *mut u8.

I am trying to do something like

*t = ptr;

I get expected u8, found *-ptr error. I understand the address ptr will be 64 bits. I want to fill up 64 bits starting from address t.

标签: pointers rust
2条回答
叛逆
2楼-- · 2019-05-31 04:10

You generally don't want to do that, but I'll trust you know what you're doing.

The key here is to understand a few things:

  • Box<T> is roughly equivalent to a *T allocated on the heap, you can use Box::into_raw to convert it into a *T.

  • If you do this, you're effectively leaking the heap allocated Box<T>, because Rust no longer knows where it is, or tracks it. You must manually convert it back into a droppable object at some point, for example using Box::from_raw.

  • You must Box::new(...) a value to ensure it is put on the heap, otherwise your raw pointer will point into the stack, which will eventually become invalid.

  • Mutable aliasing (which means two &mut T pointing to the same data) causes undefined behavior. It is extremely important to understand that undefined behavior is not triggered by concurrent writes to mutable aliases... it is triggered by mutable aliases existing at the same time, in any scope.

...but, if you really want to, you'd do it like this:

let foo_ref = Box::into_raw(Box::new(10));
let foo_ref_ref =  Box::into_raw(Box::new(foo_ref));

// Modify via raw pointer
unsafe {
    **(foo_ref_ref as *const *mut i32) = 100;
}

// Read via raw pointer 
unsafe {
    println!("{:?}", **foo_ref_ref);
}

// Resolve leaked memory
unsafe {
    Box::from_raw(foo_ref_ref);
    Box::from_raw(foo_ref);
}
查看更多
可以哭但决不认输i
3楼-- · 2019-05-31 04:22

I have a variable ptr that is of type *mut u8. How do I store the address that the ptr points to as the value of another pointer t that is also of type *mut u8

Assign one pointer to another:

use std::ptr;

fn main() {
    let ptr: *mut u8 = ptr::null_mut();
    let t: *mut u8 = ptr;
}

ptr is a pointer and the address it points to is NULL. This value is now stored in the pointer t of the same type as ptr: t points to the address NULL.

+-----+        +-----+
|     |        |     |
| ptr |        |  t  |
|     |        |     |
+--+--+        +--+--+
   |              |
   |              |
   +---->NULL<----+

If you wanted to have t be a pointer to the address of another pointer, you would need to take a reference to ptr. The types also could not be the same:

use std::ptr;

fn main() {
    let ptr: *mut u8 = ptr::null_mut();
    let t: *const *mut u8 = &ptr;
}
+-----+      +-----+
|     |      |     |
|  t  +------> ptr +----->NULL
|     |      |     |
+-----+      +-----+

I am looking for a way to write the address that the ptr points to to a specific location so that I can get the address even when I don't have t

Raw pointers have no compiler-enforced lifetimes associated with them. If you want to keep the address of something after the value has disappeared, that's an ideal case for them — you don't have to do anything:

use std::ptr;

fn do_not_dereference_this_result() -> *const u8 {
    let val: u8 = 127;
    let ptr: *const u8 = &val;
    ptr
}

fn main() {
    println!("{:p}", do_not_dereference_this_result())
}

In rarer cases, you might want to store the address in a usize (a pointer-sized integer value):

use std::ptr;

fn do_not_dereference_this_result() -> usize {
    let val: u8 = 127;
    let ptr: *const u8 = &val;
    ptr as usize
}

fn main() {
    println!("{:x}", do_not_dereference_this_result())
}

It really sounds like you are confused by how pointers work, which is a pretty good sign that you are going to shoot yourself in the foot if you use them. I'd strongly encourage you to solely use references in any important code until your understanding of pointers has increased.

查看更多
登录 后发表回答