首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么Read::read和Read::read_exact需要初始化传递给它们的缓冲区?

为什么Read::read和Read::read_exact需要初始化传递给它们的缓冲区?
EN

Stack Overflow用户
提问于 2021-12-03 21:31:45
回答 1查看 459关注 0票数 4

我有一个阅读器,它包含关于51*51网格的信息,其中网格上的每个点都由一个f32表示。我希望将这些数据读入向量中,以便我能够轻松地处理它:

代码语言:javascript
复制
pub fn from_reader<R: Read + Seek>(reader: &mut R) -> Arena {
    let arena_size = 51 * 51;
    let arena_byte_size = arena_size * size_of::<f32>();
    let mut arena = vec![0.0f32; arena_size];

    unsafe {
        let mut arena_slice =
            std::slice::from_raw_parts_mut(arena.as_mut_ptr() as *mut u8, arena_byte_size);
        let _ = reader.read(&mut arena_slice);
    };
    //...
}

该方法不方便,而且速度过慢,因为它强制所有元素用0值初始化向量。我最初只想简单地分配一个缓冲区,而不是初始化它,将数据读入其中,然后使用from_raw_parts创建一个向量。但是,我被告知这是未定义的行为,因为出于某种无法理解的原因,readread_exact要求调用方在调用它们之前初始化传递给它们的数据。

为什么是这种情况?有什么解决办法吗?铁锈小组有什么解决办法吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-12-03 21:50:44

为什么是这种情况?

因为对Read的实现者来说,首先读取传入缓冲区是有效的。如果您传入未初始化的数据,而Read的实现者查看了缓冲区,那么在纯安全代码中就会出现未定义的行为。静态地否定这一点,是锈病的一大卖点。

代码语言:javascript
复制
use std::io::{self, Read};

struct Dummy;

impl Read for Dummy {
    fn read(&mut self, buffer: &mut [u8]) -> io::Result<usize> {
        let v: u8 = buffer.iter().sum(); // Reading from the buffer
        buffer[0] = v;
        Ok(1)
    }
}

fn main() {
    let mut data = [0, 1, 2];
    Dummy.read(&mut data).unwrap();
    println!("{:?}", data);
}
  • 为什么Read::read 不阻止从缓冲区读取? 没有一种语言结构可以用来施加这种限制。与其他语言不同,Rust没有"out参数“。即使是这样,我也可以看到Read的实现者希望能够读取它刚刚编写的数据。例如,计算通过它的换行符数的读取器。
  • 为什么Read::read 不接受 MaybeUninit**?**? MaybeUninit不存在于锈蚀1.0中,它只在锈菌1.36中稳定。我们希望能够从Rust 1.0中的文件中读取。由于Rust的向后兼容保证,该方法的签名现在不能改变。
  • 为什么Read::read 不是 unsafe**?**? 这将是主要的(只有?)支持未初始化数据的技术,但代价很高。unsafe不是一个经验丰富的Rust程序员所选择的工具。当我们使用它时,我们通常会非常努力地尽量减少它的范围。 如果Read::read是不安全的,那么每个实现者都必须考虑如何正确地满足不安全的标准。对于“简单”适配器来说,这是一个很高的负担。

有什么解决办法吗?铁锈小组有什么解决办法吗?

不稳定的Read::initializer方法是一种建议的解决方案,但它可能不是首选的路径。

RFC 2930提供了一个更新的尝试,并讨论了许多背景和挑战。

另请参阅:

对于您的具体情况,您可能可以使用Read::takeRead::read_to_end将您想要的所有字节读入一个空的(未初始化的!) Vec,然后是而不复制向量。您需要以某种方式确保Vec for f32已经正确地对齐,因为它开始时只对u8

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70220906

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档