You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust中对Rc<RefCell<>>强制转换时指针地址偏移问题

Rc指针偏移问题解析

示例代码

use std::cell::RefCell;
use std::rc::Rc;

pub struct Foo<'a> {
    pub data: Rc<RefCell<&'a mut [u8]>>,
}

fn main() {
    let x: u64 = 0x300007f50;
    let x_addr: u64 = &x as *const u64 as u64;
    unsafe {
        #[allow(invalid_reference_casting)]
        let x = &mut *(x_addr as *mut Foo);
        println!("{:?}", x.data.as_ptr());
    }
}

程序输出

该程序的输出为:0x300007f68

原因分析

你遇到的问题本质是非法内存类型转换加上Rc<T>的内部结构导致的指针偏移,拆解如下:

  1. 非法的内存类型转换
    你将存储u64值0x300007f50的内存地址,强制转换成*mut Foo指针,相当于把这段仅存一个u64值的内存,当作Foo结构体实例来解析。但这段内存的布局完全不符合Foo的结构要求,后续操作本质是在读取无意义的内存数据。

  2. Rc<T>的内部结构导致偏移
    Rc<T>是Rust的单线程引用计数智能指针,它的内部包含一个堆上控制块,结构大致为:

struct RcBox<T> {
    strong: std::cell::Cell<usize>, // 强引用计数
    weak: std::cell::Cell<usize>,   // 弱引用计数
    value: T,                       // 实际存储的数据
}

Rc<T>实例本身只是一个指向该控制块的指针。当调用Rc::as_ptr()时,返回的是控制块中value字段的地址——也就是Rc指针地址加上控制块前两个字段的字节数(64位系统下每个计数占8字节,共16字节),再加上内存对齐填充(此处为额外8字节,总偏移24字节即0x18)。

在你的代码中,被当作Rc指针的是原u64值0x300007f50,所以as_ptr()返回的地址就是0x300007f50 + 0x18 = 0x300007f68,这就是你看到的偏移结果。

  1. 预期错误的根源
    你误以为将u64值的地址转换成Foo指针后,x.data.as_ptr()会返回原u64的值,但实际上:
  • x.data是从非法内存中解析出的Rc实例,其内部指针是原u64的值0x300007f50
  • as_ptr()返回的是该Rc指向的控制块中数据区域的地址,而非Rc指针本身或原u64的值

内容的提问来源于stack exchange,提问作者Suraj Choudhary

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 08:51:11