【问题标题】:Getting pointer by &str通过 &str 获取指针
【发布时间】:2019-07-16 16:06:17
【问题描述】:

考虑这个伪代码:

    let k = 10;
    let ptr = &k as *const k;
    println!("{:p}", ptr); // prints address of pointer
    let addr = format!("{:p}", ptr);

    super-unsafe {
    // this would obviously be super unsafe. It may even cause a STATUS_ACCESS_VIOLATION if you try getting memory from a page that the OS didn't allocate to the program!

    let ptr_gen = PointerFactory::from_str(addr.as_str()); 

    assert_eq!(k, *ptr_gen);
    }

伪代码传达了这个想法:我希望能够通过 &str 表示获得指向某个内存地址的指针。这……可能吗?

【问题讨论】:

  • 为什么不能先把字符串表示回一个无符号整数?
  • 啊,这会通过 transmute 或 std::mem 或 std::ptr 下的东西来完成吗?
  • 另外,如果我在学习低级编码时弄错了,请纠正我,但内存中的所有指针不都是相同大小的吗? (需要知道无符号使用多少位)
  • 这里的要领在here回答,使用from_str_radix()进行转换例如"0xdeadbeef" 为整数;从那里你投射到一个 ptr* 并希望没有人在看

标签: pointers rust unsafe


【解决方案1】:

所以基本上你想要做的是将字符串解析回整数 (usize),然后将该值解释为指针/引用

fn main()
{
    let i = 12i32;
    let r = format!("{:p}", &i);


    let x = unsafe
    {
        let r = r.trim_start_matches("0x");
        &*(usize::from_str_radix(&r, 16).unwrap() as *const i32)
    };

    println!("{}", x);
}

您可以在playground 中亲自尝试。

如您所见,您甚至不需要将引用转换为原始指针,{:p} 格式化程序负责将其表示为内存位置(索引)。


更新:正如 E_net4 在评论部分提到的,这里最好使用usize,这是与机器大小不同的架构定义。 transmute 不是必需的,所以我删除了它。然而,对于试图做上述事情的人来说,关于未定义行为的第三点似乎是显而易见的。这个答案提供了一种实现OP要求的方法,这并不意味着这应该用于学术/实验目的以外的任何其他用途:)

【讨论】:

  • 谢谢!我很高兴我们现在在 SO 上回答了这个问题。尽管当 Rust 使用大酒瓶而不是气球进行保护时,这并不意外。
  • 不用担心,真的,但要小心你将要使用它! (我警告过你;))另外,我拒绝了你的编辑,因为这无助于理解 IMO。如果您愿意,我建议您将其作为单独的答案发布。
  • 有了互斥锁和一些图表,我确信我能够在任何不想要的事情发生之前退出 ;)。谢谢,编辑没有问题。
  • 值得一提的是,这个解决方案存在多个问题: 1. 它只适用于64位指针宽度目标,应该使用usize而不是u64; 2. 不需要transmute,您可以将usize 值转换为带有as 的原始指针并取消引用它; 3. 这将创建一个具有 n 无限生命周期的引用,因此它可以比原始值活得更长。请参阅 playground example 并建议更改 + UB。
  • 非常有趣的添加 Enet。谢谢!
猜你喜欢
  • 2011-09-17
  • 2021-06-03
  • 1970-01-01
  • 2011-12-21
  • 2012-01-07
  • 1970-01-01
  • 2023-03-16
  • 1970-01-01
  • 2014-08-15
相关资源
最近更新 更多