dom*_*min 4 heap stack dynamic rust memory-safety
尝试使用编程语言Rust,我发现编译器能够非常准确地跟踪堆栈中某些结构的字段的移动(它确切地知道哪个字段已移动).但是,当我将结构的一部分放入a Box(即将其放入堆中)时,编译器不再能够确定在取消引用该框之后发生的所有事件的字段级移动.它将假设"盒子内部"的整个结构已经移动.让我们首先看一下一切都在堆栈上的例子:
struct OuterContainer {
inner: InnerContainer
}
struct InnerContainer {
val_a: ValContainer,
val_b: ValContainer
}
struct ValContainer {
i: i32
}
fn main() {
// Note that the whole structure lives on the stack.
let structure = OuterContainer {
inner: InnerContainer {
val_a: ValContainer { i: 42 },
val_b: ValContainer { i: 100 }
}
};
// Move just one field (val_a) of the inner container.
let move_me = structure.inner.val_a;
// We can still borrow the other field (val_b).
let borrow_me = &structure.inner.val_b;
}
Run Code Online (Sandbox Code Playgroud)
现在是相同的例子,但只有一个小改动:我们把它InnerContainer放进一个盒子里(Box<InnerContainer>).
struct OuterContainer {
inner: Box<InnerContainer>
}
struct InnerContainer {
val_a: ValContainer,
val_b: ValContainer
}
struct ValContainer {
i: i32
}
fn main() {
// Note that the whole structure lives on the stack.
let structure = OuterContainer {
inner: Box::new(InnerContainer {
val_a: ValContainer { i: 42 },
val_b: ValContainer { i: 100 }
})
};
// Move just one field (val_a) of the inner container.
// Note that now, the inner container lives on the heap.
let move_me = structure.inner.val_a;
// We can no longer borrow the other field (val_b).
let borrow_me = &structure.inner.val_b; // error: "value used after move"
}
Run Code Online (Sandbox Code Playgroud)
我怀疑它与堆栈的性质和堆的性质有关,前者是静态的(至少每个堆栈帧),而后者是动态的.也许编译器需要安全地使用它,因为我无法清楚地表达/识别.
DK.*_*DK. 12
在抽象的,一个struct在栈上是那种只是在一个共同的名字变量的一群.编译器知道这一点,并且可以将结构分解为一组独立的堆栈变量.这使它可以独立跟踪每个场的移动.
它不能用a Box或任何其他类型的自定义分配来执行,因为编译器不控制Boxes. Box只是标准库中的一些代码,而不是语言的固有部分. Box无法推断自身的不同部分突然变得无效.当摧毁一个时Box,它的Drop实现只知道毁灭一切.
换句话说:在堆栈上,编译器处于完全控制状态,因此可以执行奇特的操作,例如破坏结构并逐个移动它们.一旦自定义分配进入图片,所有投注都会关闭,编译器必须退出并停止尝试变得聪明.