rust - 如何使用不安全代码在由 RefCell/RwLock Ref/Guard 封装的集合上返回 Iterator?

标签 rust unsafe

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

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

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

我的想法是将守卫包装在一个实现Iterator 的结构中。除了守卫之外,还存储了一个迭代器,它将从存储的守卫中创建:

struct MapIter<'a> {
    guard: RwLockReadGuard<'a, HashMap<i32, i32>>,
    iter:  Iter<'a, i32, i32>,
}

它是用这些行创建的:

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了:

impl<'a> Iterator for MapIter<'a> {
    type Item = (&'a i32, &'a i32);

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

这段代码安全吗?

请参阅 playground 中的此代码.

此外,我收到了一个琐碎的类型转换警告

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() };
   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |

如何解决这个问题?

最佳答案

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

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.

the playground这会编译,但不好,因为 r 包含对清除 HashMap 时无效的数据的引用。

Vladimir Matveev's answer to a similar question更详细地解释了为什么这是不合理的,并包含以下简明摘要:

You cannot do this because it would allow you to circumvent runtime checks for uniqueness violations.

关于rust - 如何使用不安全代码在由 RefCell/RwLock Ref/Guard 封装的集合上返回 Iterator?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51863819/

相关文章:

rust - 为什么二进制 + 运算符不能与两个 &mut int 一起使用?

rust - 在 Rust 中返回一个引用和被引用的对象

c# - 使用 Action<PointerClass*> 作为参数

arrays - 是否可以从终端定义一个常量值?

algorithm - 获取 BTreeMap 中最大值的键的惯用方法?

c# - 此处是否需要 GC.KeepAlive,或者我可以依靠局部变量和参数来保持对象的事件状态吗?

c# - 将 System.Decimal 转换为 System.Guid

java - 如何获取 sun.misc.Unsafe 的实例?

path - 我可以使用 `std::path::Path` 的 `strip_prefix` 来替换动态前缀吗?

java - 不安全的类加载问题?