首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么在运行时调用Iterator特性对象的next会给我一个“内存不足”?

为什么在运行时调用Iterator特性对象的next会给我一个“内存不足”?
EN

Stack Overflow用户
提问于 2016-07-07 20:26:01
回答 1查看 206关注 0票数 2

我在Rust中实现了一个BoxedIterator,它只是将另一个Iterator作为一个特征对象。完全实现是在Github上进行的。为什么Rust在编译这段代码时毫无怨言,但是当它第一次尝试在next上调用Box中的Iterator特性对象时,却以“内存不足”消息失败了?

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

代码语言:javascript
复制
//! 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());
}

我不认为我将使用这段代码,因为我已经意识到我的用例需要完全遍历Iterator of Results来提取任何错误,所以我最好在此时将它们收集到Vec中。但我还是对这个OOM很好奇。

在创建一个最小的示例时,我发现如果不执行File,就会得到一个分段错误:

代码语言:javascript
复制
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,只需使用collect创建一个BoxedIterator,代码就会像预期的那样工作:

代码语言:javascript
复制
use iterator::BoxedIterator;

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

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

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-07-08 04:25:11

FromIterator的实现是不正确的;具体来说,不允许将I::IntoIter: 'static绑定到该位置。实现的边界必须与特征本身的界限相匹配。编译器应该诊断这一点,但目前没有

在更高的层次上,我不知道你想做什么。您期望File句柄存储在哪里?你通常会写这样的东西:

代码语言:javascript
复制
let files: Result<Vec<File>, io::Error> =
    ["/bin/bash"].iter().cloned().map(File::open).collect();
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38254647

复制
相关文章

相似问题

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