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
相关产品推荐
相关产品推荐

