【发布时间】:2021-06-26 15:07:11
【问题描述】:
我的结构有不安全的代码和指向另一种结构的原始可变指针。不安全结构只能在另一个结构的生命周期内使用,但您不能为指针指定生命周期。我发现std::marker::PhantomData 可以用于这个未使用的生命周期问题,但我在让它工作时遇到问题。我不确定这是无效用例还是我做错了什么。
use std::marker::PhantomData;
pub struct Test {
value: u32,
}
impl Test {
pub fn value(&self) {
println!("{}", self.value)
}
pub fn set_value(&mut self, value: u32) {
self.value = value;
}
}
// I want compiler to complain about the lifetime of test
// so that UnsafeStruct is not used after test is dropped
pub struct UnsafeStruct<'a> {
test: *mut Test,
phantom: PhantomData<&'a mut Test>,
}
impl<'a> UnsafeStruct<'a> {
pub fn new(test: &'a mut Test) -> UnsafeStruct<'a> {
UnsafeStruct {
test: test,
phantom: PhantomData,
}
}
pub fn test_value(&self) {
unsafe { println!("{}", (*self.test).value) }
}
pub fn set_test_value(&mut self, value: u32) {
unsafe {
(*self.test).set_value(value);
}
}
}
fn main() {
// No borrow checker errors
// but the compiler does not complain about lifetime of test
let mut unsafe_struct: UnsafeStruct;
{
let mut test = Test { value: 0 };
unsafe_struct = UnsafeStruct {
test: &mut test,
phantom: PhantomData,
};
unsafe_struct.set_test_value(1);
test.value();
test.set_value(2);
unsafe_struct.test_value();
}
unsafe_struct.set_test_value(3);
unsafe_struct.test_value();
// Lifetime errors caught
// but there will be borrow checker errors if you fix
let mut unsafe_struct: UnsafeStruct;
{
let mut test = Test { value: 0 };
unsafe_struct = UnsafeStruct::new(&mut test);
unsafe_struct.set_test_value(1);
test.value();
test.set_value(2);
unsafe_struct.test_value();
}
unsafe_struct.set_test_value(3);
unsafe_struct.test_value();
// Borrow checker errors when you fix lifetime error
{
let mut test = Test { value: 0 };
let mut unsafe_struct: UnsafeStruct;
unsafe_struct = UnsafeStruct::new(&mut test);
unsafe_struct.set_test_value(1);
test.value();
test.set_value(2);
unsafe_struct.test_value();
}
}
如果我直接创建UnsafeStruct,编译器不会捕获生命周期错误,我还是想使用构造函数。如果我使用构造函数,那么我有借用检查器错误。是否可以修复此代码,以使编译器在尝试在相应 Test 的生命周期之外使用 UnsafeStruct 时会出错,但不会出现示例中显示的借用检查错误?
【问题讨论】:
-
为什么不直接使用可变引用?
-
如果您的意思是 UnsafeStruct 中的可变引用,由于我需要不安全的行为而无法正常工作。
-
你能解释一下“我需要不安全的行为”是什么意思吗?
-
我需要原始指针功能。我需要直接在借用检查规则之外操作结构。
-
您可以在结构中存储可变引用,并在需要时将其转换为不安全代码中的原始指针。
标签: rust