stream - 使用 PhantomData 和 unsafe 将流式迭代器作为普通迭代器处理

标签 stream iterator rust unsafe

我知道下面的代码是 hacky,但它可以被称为安全和惯用的 Rust 吗?有更好的方法吗?

// needs to do 'rustup default nightly' to run under valgrind
// #![feature(alloc_system, global_allocator, allocator_api)]
// extern crate alloc_system;
// use alloc_system::System;
// #[global_allocator]
// static A: System = System;

struct Foo<'a> {
    v: Vec<u8>,
    pos: usize,
    phantom: std::marker::PhantomData<&'a u8>,
}

impl<'a> Iterator for Foo<'a> {
    type Item = &'a mut u8;

    fn next(&mut self) -> Option<&'a mut u8> {
        let r = self.v.get_mut(self.pos);
        if r.is_some() {
            self.pos += 1;
            unsafe { Some(&mut *(r.unwrap() as *mut u8)) }
        } else {
            None
        }
    }
}

impl<'a> Foo<'a> {
    fn reset(&mut self) {
        self.pos = 0;
    }
}

fn main() {
    let mut x = Foo {
        v: (1..10).collect(),
        pos: 0,
        phantom: std::marker::PhantomData,
    };
    let vp = x.v.as_ptr();

    {
        for i in &mut x {
            println!("{}", i);
        }
    }
    {
        x.reset();
    }
    {
        for i in &mut x {
            *i *= *i;
        }
    }
    {
        x.reset();
    }
    {
        for i in &mut x {
            println!("{}", i);
        }
    }

    assert!(vp == x.v.as_ptr());
}

在评论中写一点,Valgrind 告诉我没有泄漏,结果在 Rust 1.26.0-nightly 和 1.25.0 下符合预期。

相关:

最佳答案

此代码不安全。该类型的用户可以选择任何生命周期,包括'static:

fn constructor() -> Foo<'static> {
    Foo {
        v: vec![42; 10],
        pos: 0,
        phantom: std::marker::PhantomData,
    }
}

fn example() -> &'static u8 {
    let mut f = constructor();
    f.next().unwrap()
}

fn main() {
    println!("example: {}", example());
}

在这里,example 返回对不再在范围内的变量的引用,访问无效内存并破坏您必须坚持的限制。


an example of how you could write this code在另一个问答中没有任何unsafe

关于stream - 使用 PhantomData 和 unsafe 将流式迭代器作为普通迭代器处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49683888/

相关文章:

c++ - 我在 map 中有 9 个元素,但 begin() 和 end() 之间的距离只有 2

c++:遍历一组 vector

Rust 声称此模式案例无法访问,为什么?

rust - Rust借用可能未初始化的变量-作为程序员,这对我来说很明显,它将始终被初始化

scala - Scala 中有 FIFO 流吗?

javascript - 你如何在 Gulp 中创建一个空流?

java流空检查

c++ - std::string::iterator 偏移并返回

java - 有没有一种方法可以使用 Function< 将多个方法减少为一个方法? super T, ?> 作为方法参数?

linux - 我如何使用 Cargo 构建目标文件?