首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在使用不安全代码封装的集合上返回Iterator?

如何在使用不安全代码封装的集合上返回Iterator?
EN

Stack Overflow用户
提问于 2018-08-15 17:45:24
回答 1查看 592关注 0票数 1

关于这一主题,已经提出了多个问题:

答案或多或少:这是不可能的(没有不安全的)。

我自己试过这种不安全的变体,想问一下这种方法是否安全。

我的想法是,我把保护包在一个实现Iterator的结构中。除了保护之外,还存储了一个迭代器,该迭代器将从存储的保护程序中创建:

代码语言:javascript
复制
struct MapIter<'a> {
    guard: RwLockReadGuard<'a, HashMap<i32, i32>>,
    iter:  Iter<'a, i32, i32>,
}

它是用以下行创建的:

代码语言:javascript
复制
impl<'a> MapIter<'a> {
    fn new(map: &'a RwLock<HashMap<i32, i32>>) -> Box<Self> {
        // create a `box Self`
        // the iterator remains uninitialized.
        let mut boxed = Box::new(Self {
            guard: map.read().expect("ToDo"),
            iter:  unsafe { mem::uninitialized() },
        });

        // create the iterator from `box Self`.
        boxed.iter = unsafe { 
            (*(&boxed.guard as *const RwLockReadGuard<'a, HashMap<i32, i32>>)).iter() 
        };
        boxed
    }
}

现在它可以实现Iterator

代码语言:javascript
复制
impl<'a> Iterator for MapIter<'a> {
    type Item = (&'a i32, &'a i32);

    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next()
    }
}

这密码安全吗?

请在游乐场上查看此代码的实际操作。

此外,我还得到了一个微不足道的抛出警告。

代码语言:javascript
复制
warning: trivial cast: warning: trivial cast: `&std::sync::RwLockReadGuard<'_, std::collections::HashMap<i32, i32>>` as `*const std::sync::RwLockReadGuard<'a, std::collections::HashMap<i32, i32>>`. Cast can be replaced by coercion, this might require type ascription or a temporary variable
   |
   | unsafe { (*(&boxed.guard as *const RwLockReadGuard<'a, HashMap<i32, i32>>)).iter() };
   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |

怎么才能避开这一切?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-08-15 19:27:25

不这不安全。我可以使用Container在安全代码中创建一个悬空引用:

代码语言:javascript
复制
let container = Container::new();       // create a container
let r = {
    let mut it = container.iter();
    it.next()                           // obtain a reference to part of it
};
container.map.write().unwrap().clear(); // empty the container
println!("{:?}", r);                    // oh dear.

操场中,这是不太好的编译,因为r包含对数据的引用,这些引用在清除HashMap时无效。

弗拉基米尔·马特维耶夫对类似问题的回答更详细地解释了为什么这是不合理的,并包含以下简明摘要:

您不能这样做,因为它将允许您绕过运行时检查唯一性冲突。

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

https://stackoverflow.com/questions/51863819

复制
相关文章

相似问题

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