dynamic - Rust 中的所有权跟踪 : Difference between Box<T> (heap) and T (stack)

标签 dynamic rust heap-memory stack-memory memory-safety

用 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"
}

我怀疑它与堆栈的性质与堆的性质有关,前者是静态的(至少每个堆栈帧),后者是动态的.也许由于某种原因我无法很好地表达/识别,编译器需要谨慎行事。

最佳答案

在抽象中,堆栈上的struct 只是一种 普通名称下的一堆变量。编译器知道这一点,可以将结构分解为一组独立的堆栈变量。这让它可以独立跟踪每个字段的移动。

它不能用 Box 或任何其他类型的自定义分配来做到这一点,因为编译器不控制 Boxes。 Box 只是标准库中的一些代码,不是语言的固有部分。 Box 无法推断其自身的不同部分突然变得无效。当需要销毁 Box 时,它的 Drop 实现只知道销毁一切

换句话说:在堆栈上,编译器处于完全控制之下,因此可以做一些奇特的事情,比如分解结构并将它们零碎地移动。一旦自定义分配进入画面,所有的赌注都会落空,编译器必须后退并停止试图变得聪明。

关于dynamic - Rust 中的所有权跟踪 : Difference between Box<T> (heap) and T (stack),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44081865/

相关文章:

JAVA : How many Objects will be created ? 为什么?

c++ - 声明动态内存语句 C++

javascript - 如何使用 JavaScript 触发器管理 PHP 列表

rust - 无需代码重复即可在单项测试中多次 panic

rust - 从 io::Result() 获取堆栈跟踪?

c++ - 在堆栈上创建临时对象作为参数

用于动态创建的 html 页面的 php 或 jquery?

javascript - 在原型(prototype)中使用 JavaScript 发出居中动态大小的对象

loops - 在Rust中进行迭代和操作的最佳/理想方式是什么

C++:什么时候使用 "new"什么时候不用? |添加:不重复