rust 通过使用“static”来保存对同一结构的属性的引用是否安全?

k4emjkb1  于 2023-10-20  发布在  其他
关注(0)|答案(1)|浏览(132)

一个棘手的问题是,如果没有不安全的块,就不可能解决这个问题,那就是在一个结构中引用这个结构的其他属性所拥有的东西。
然而,对于不安全的块,这很容易,你可以这样做:

struct Foo {
    bar: &'static str,
    foo: String
}

impl Foo {
    pub fn new(s: String) -> Foo {
        Foo {
            bar: unsafe { ::std::mem::transmute(&s[..]) },
            foo: s
        }
    }
}

问题是:假设之前定义的结构Foo的方法没有给&mut访问它的权限(因此结构在创建后永远不会被修改),知道String的数据是堆分配的,那么这段代码实际上是安全的吗(根据rust的“安全”含义)?如果没有,在哪些情况下可能出现问题?

gwo2fgha

gwo2fgha1#

&mut访问并不重要。重要的是String永远不会改变(至少&'static str不会改变),其他数据可以改变。此外,如果&mut允许第三方代码更改字符串,那么他们也可以通过继承的可变性在没有指针的情况下更改它:

let x = Foo::new(string);
let mut x = x;
x.foo = other_string;
println!("{}", x.bar); //

因此,至少您必须保持属性私有,并审计同一模块中的所有代码(不仅仅是impl Foo!)。但还有另一个问题:如果你 * 曾经 * 分发&'static str,那么是的,它是不安全的:

let x = Foo::new(string);
let s: &'static str = obtain_str(x);
drop(x);
println!("{}", s); // use after free

所以你能安全地用这种自我参照做的事情是非常有限的。第二个问题,* 也许 *,可以通过适当地使用生命期来避免,但是这进入了一个领域,在这个领域中,我不愿意在没有详细的半正式论证的情况下接受安全性。
对于我想象的用例,咬紧牙关远离unsafe可能更容易。

相关问题