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

Rust中同一数据的&[u32]与&mut [u32]共存是否为未定义行为?

SPI驱动原地收发的安全实现疑问

现有精简驱动代码

use tokio::{join, sync::mpsc};

async fn spi_transmit(write_buf: &[u32], read_buf: &mut [u32]) {
    assert_eq!(read_buf.len(), write_buf.len());
    let (write_fifo, mut read_fifo) = mpsc::channel(2);

    let write_task = async {
        // 模拟SPI总线返回发送数据+20,仅作演示
        for val in write_buf {
            write_fifo.send(*val + 20).await.unwrap();
        }
    };

    let read_task = async {
        for val in read_buf {
            *val = read_fifo.recv().await.unwrap();
        }
    };

    join!(write_task, read_task);
}

#[tokio::main]
async fn main() {
    let buf_out = [1, 2, 3, 4];
    let mut buf_in = [0, 0, 0, 0];

    spi_transmit(&buf_out, &mut buf_in).await;

    println!("{:?}", buf_in);
}

运行输出:

[21, 22, 23, 24]

核心API为async fn spi_transmit(write_buf: &[u32], read_buf: &mut [u32])。

原地收发的实现尝试

需要实现async fn spi_transmit_in_place(read_write_buf: &mut [u32]),使用同一缓冲区完成收发,最终缓冲区存储读取的数据。已知读写操作绝不会重叠,总是先读取数据,再在非重叠时间点执行写入操作。

尝试实现如下:

async fn spi_transmit_in_place(read_write_buf: &mut [u32]) {
    let write_buf = unsafe {
        let data = read_write_buf.as_ptr();
        let len = read_write_buf.len();
        std::slice::from_raw_parts(data, len)
    };

    spi_transmit(write_buf, read_write_buf).await
}

#[tokio::main]
async fn main() {
    let mut buf = [1, 2, 3, 4];
    spi_transmit_in_place(&mut buf).await;
    println!("{:?}", buf);
}

运行输出:

[21, 22, 23, 24]

代码可正常运行,但Miri检测不通过。

疑问

  • 上述实现是否安全?是否属于未定义行为?
  • 若属于未定义行为,是否必须用裸指针重写spi_transmit?或是有其他解决方案?
  • 核心疑问:同一数据同时存在&[u32]和&mut [u32]本身是否属于未定义行为?

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 00:12:47