iterator - 为什么在 Iterator 特征对象上调用 next 在运行时会给出 "out of memory"?

标签 iterator out-of-memory rust

我实现了 BoxedIterator在 Rust 中,这只是另一个 Iterator作为特征对象。完整实现位于 Github 。为什么 Rust 毫无怨言地编译此代码,但在第一次尝试调用 next 时却失败并显示“内存不足”消息 (OOM)关于Iterator Box 中的特征对象?

据我所知,它在失败之前没有分配太多内存,所以我倾向于认为 OOM 消息不正确。

//! BoxedIterator just wraps around a box of an iterator, it is an owned trait object.
//! This allows it to be used inside other data-structures, such as a `Result`.
//! That means that you can `.collect()` on an `I where I: Iterator<Result<V, E>>` and get out a
//! `Result<BoxedIterator<V>, E>`. And then you can `try!` it. At least, that was my use-case.

use std::iter::FromIterator;
use std::iter::IntoIterator;

pub struct BoxedIterator<T> {
    iter: Box<Iterator<Item = T>>,
}

impl<T> Iterator for BoxedIterator<T> {
    type Item = T;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next() // The OOM comes from this call of `next`
    }
}

impl<T> FromIterator<T> for BoxedIterator<T> {
    fn from_iter<I>(iter: I) -> Self
        where I: IntoIterator<Item = T>,
              I::IntoIter: 'static
    {
        BoxedIterator { iter: Box::new(iter.into_iter()) }
    }
}

use std::fs::File;
use std::io;

fn main() {
    let iter: Result<BoxedIterator<File>, io::Error> =
        vec!["/usr/bin/vi"].iter().cloned().map(File::open).collect();
    let mut iter = iter.unwrap();

    println!("{:?}", iter.next());
}

我认为我不会使用这段代码,因为我认为我的用例需要遍历 IteratorResult s 完全提取任何错误,所以我不妨将它们收集在 Vec 中在那时候。但我还是对这个OOM很好奇。

在创建一个最小的示例时,我发现如果不执行文件 IO,就会出现段错误:

use iterator::BoxedIterator;

fn main() {
    let iter: Result<BoxedIterator<&str>, ()> = 
        vec![Ok("test1"), Ok("test2")].iter().cloned().collect();
    let mut iter = iter.unwrap();

    println!("{:?}", iter.next());
}

如果我不使用任何Result ,只需创建一个 BoxedIteratorcollect ,代码按预期工作:

use iterator::BoxedIterator;

fn main() {
    let mut iter: BoxedIterator<&str> = vec!["test1", "test2"].iter().cloned().collect();

    println!("{:?}", iter.next());
    // prints: Some("test1")
}

最佳答案

您的 FromIterator 实现不正确;具体来说,您不允许在该位置放置 I::IntoIter: 'static 绑定(bind)。您的实现的界限必须与特征本身的界限相匹配。编译器应该对此进行诊断,but currently doesn't .

在更高的层面上,我不确定你想做什么。您希望将 File 句柄存储在哪里?你通常会写这样的东西:

let files: Result<Vec<File>, io::Error> =
    ["/bin/bash"].iter().cloned().map(File::open).collect();

关于iterator - 为什么在 Iterator 特征对象上调用 next 在运行时会给出 "out of memory"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38254647/

相关文章:

rust - 闭包内容器对象的生命周期推理

c++ - 是否保证每个迭代器仅调用一次remove_if谓词?

java.util.Iterator 但无法导入 java.util.Iterator

c++ - map /设置迭代器不可递增,我无法从头开始重新启动 map

c# - 模拟磁盘空间不足异常

java - 内存中的大型对象的 JVM 问题

c++ - 在数组中查找最小值

android - NullPointerException 从文件 Android 重新缩放位图

linux - 如何获取从 Rust 程序内部运行的 Bash 脚本的退出代码?

rust - 如何隐藏子模块中的方法但仍可从父模块中使用它?