【发布时间】:2017-10-20 06:45:19
【问题描述】:
用编程语言 Rust 进行实验,我发现编译器能够非常准确地跟踪 堆栈上某个结构的字段 的移动(它确切地知道 什么 字段已移动)。
但是,当我将结构的一部分放入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;
}
现在是相同的示例,但有一个小改动:我们将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"
}
我怀疑这与 堆栈的性质与堆的性质有关,前者是静态的(至少每个堆栈帧),而后者是动态的.也许由于某种原因我不能很好地表达/识别,编译器需要谨慎行事。
【问题讨论】:
-
i32 是 Copy 类型,因此数据被复制而不是移动。
-
但是,我正在对周围的结构 (
ValContainer) 进行操作,而不是对包含的整数进行操作。据我所知,自定义结构类型默认不是Copyable。 -
是的,你是对的。没有正确阅读您的代码。
标签: dynamic rust heap-memory stack-memory memory-safety