我在Rust中实现了一个BoxedIterator
,将另一个Iterator
装箱为特征对象。完整的实现在Github上。为什么Rust第一次尝试在next
中调用Iterator
特质对象上的Box
时,会毫无提示地编译此代码,但失败并显示“内存不足”消息(OOM)?
据我所知,它在失败之前不会分配太多内存,因此我倾向于认为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());
}
我认为我不会使用此代码,因为我发现我的用例将需要完全遍历
Iterator
的Result
以提取任何错误,因此我不妨在此时将它们收集在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
,只需使用BoxedIterator
创建一个collect
,该代码将按预期工作: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 trait对象上调用next会给我一个 “out of memory”?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38254647/