【问题标题】:Convert pointer address to original instance将指针地址转换为原始实例
【发布时间】:2022-07-07 20:36:20
【问题描述】:

如果我在 Rust 中获得一个指针的地址并将其转换为数字类型,例如这样:

let map: HashMap<i32, String> = HashMap::new();
let ptr = std::ptr::addr_of!(map); 
let ptri = ptr as i32;

我可以从ptri 变量中取回原始实例(在这种情况下为HashMap)吗?

类似于 C 语言:

HashMap *map = (HashMap*)(uintptr_t)ptri;

【问题讨论】:

  • Rust 相当于 uintptr_tusize,所以你可能想要 let ptri = ptr as usize
  • 请注意,这是否有效尚未确定——目前无法找到相关讨论,但关键词是“指针出处”。
  • @Cerberus 它被允许的,并且总是会被允许(暴露出处和天使的不确定性,虽然as演员可能在(遥远的)未来被弃用,但它' 将始终与 expose_addr()/from_exposed_addr() 一起使用)。唯一的讨论是关于添加更好的方法(您正在寻找“严格出处”的努力)。
  • 吹毛求疵:addr_of!()?只需使用&amp;map as *const _

标签: pointers rust


【解决方案1】:

仅当您在 32 位计算机上时。否则,指向i32 的指针转换将被截断,您将无法取回原始地址。切换到使用 isize 来处理指针大小的整数,您可以将指针转换回 HashMap 类型,取消引用它,然后借用该哈希映射的实例:

use std::collections::HashMap;

fn main() {
    let map: HashMap<i32, String> = HashMap::new();
    let ptr = std::ptr::addr_of!(map);
    let ptri = ptr as isize;

    println!("{:?}", map);
    println!("{:?}", ptr);
    println!("{:?}", ptri);
    println!("{:?}", unsafe {
        &*(ptri as *const HashMap<i32, String>)
    });
}

【讨论】:

  • 您不想使用readread_unaligned,因为您会导致双重释放(除非您已将原始值适当地准备为不释放)
  • @kmdreko 我没有意识到有一种方法可以取消引用原始指针没有双重释放的可能性。我认为这是unsafe 块的目的之一,有没有更好的“安全”方式?
  • 您可以将指针直接转换为引用(需要unsafe):ptri as *const HashMap&lt;i32, String&gt; as &amp;HashMap&lt;i32, String&gt;
  • 编译器让我在演员表之前 deref 和借用 (&amp;*(ptri as *const HashMap&lt;i32, String&gt;) as &amp;HashMap&lt;i32, String&gt;),但这很整洁。我可以看到它是如何获得引用而不是拥有一个浅拷贝(防止双重释放),但&amp;* 看起来真的很奇怪。如果你回答这个问题,我会投票给你。
  • 编译器为我建议了更短的版本,只有&amp;*(ptri as *const HashMap&lt;i32, String&gt;)。非常感谢,我肯定会投票给你们两个。
猜你喜欢
  • 1970-01-01
  • 2021-10-31
  • 1970-01-01
  • 2017-07-05
  • 2015-03-10
  • 2014-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多