【问题标题】:What goes on the stack and what goes on the heap in Rust?在 Rust 中,堆栈上发生了什么,堆上发生了什么?
【发布时间】:2018-10-02 20:58:25
【问题描述】:

我真的对 Rust 的内存分配系统感到困惑。

在 Java 中,您使用 new 在堆上分配内存。在 C 中,您使用 malloc(),其他所有内容都在堆栈中。

我认为,在 Rust 中,Box<T> 在堆上分配内存,但在阅读 "Defining Our Own Smart Pointer" section in chapter 15.2 in The Rust Programming Language 之后,MyBox<T> 似乎没有任何特殊注释来使 T 的值存在于堆上。

  1. 堆栈上到底发生了什么,堆上发生了什么?

  2. MyBox<T>的实现与Box<T>本质上是一样的吗?

  3. 如果实现相同,是什么让T 存储在堆上而不是堆栈上?

  4. 如果实现不同,是什么让Box<T> 在堆上分配内存?

【问题讨论】:

  • (实际上,在C语言中,这些都不是堆和栈的概念,malloc只是需要给内存,不管它是什么,malloc的一些实现使用“栈”,但C没有关心,这就是重点,C 为你抽象了这个(但是在后台 malloc 经常使用“堆”))
  • 尽量不要考虑“堆栈”与“堆”,因为这两个概念确实过时并且几乎不相关,因为编译器可以并且会严重模糊这些界限。思考而不是“本地”与“可共享”或“动态”。
  • 是的,我确实是这样想的,我只是想知道引擎盖下发生了什么,以及 rust 如何在没有明确调用“new”之类的东西的情况下实现这一点
  • 最好发布单独的问题,而不是将您的问题合并为一个。这样,它可以帮助回答您的问题的人以及寻找您的问题的其他人。
  • @JimMorrison:关于问题 3-4:您链接到的书指出以下内容:“注意:我们即将构建的 MyBox 类型和真正的 Box:我们的版本不会将其数据存储在堆上。”所以MyBox 和普通的Box 是根本不同的!

标签: rust


【解决方案1】:
  1. 这很难说。通常 Rust 会避免在堆上分配任何东西。编译器永远不会在堆上进行隐式分配,但库函数可能会为您完成。至少任何动态大小的东西(例如Vec<T>)都需要在引擎盖下堆上一些东西,其余的,文档应该提示它。

    请注意,即使在 C 语言中,许多函数也可以在不显式调用 malloc 的情况下进行堆分配。例如。我最近不得不调试内存泄漏,开发人员调用getaddrinfo 没有相应的freeaddrinfo,忽略此函数在堆上分配内存。不过,感谢RAII,此类错误在 Rust 中应该很少见。

  2. 一点也不!本书在这里简化了一些事情,以避免对本节不重要的细节。

  3. Box 是一个内置的编译器。在引擎盖下分配内存的是一个分配器,如liballoc 中定义的那样。您可以将此分配器视为提供类似malloc 的功能。在实践中,默认分配器在大多数目标上使用jemalloc,也可以使用自定义分配器,例如alloc_system crate 使用系统的malloc/realloc/free 函数来构建其分配器.

【讨论】:

  • 这实际上是我的想法(那个 Box 得到了“特殊待遇”),但我在网上找不到任何可以证实这一点的东西。感谢您的回答!
  • @Jim 关于Box 处理内存的唯一特别之处是您可以使用* 移出它(释放后备内存)。关于Box 的所有其他内容都可以使用liballoc 作为后端以普通的Rust 代码编写。
  • 参见 cs242.stanford.edu/f19/lectures/07-2-smart-pointers 了解使用原始指针和特征实现简化 Box、Rc 的详细信息
猜你喜欢
  • 2020-08-22
  • 1970-01-01
  • 2019-10-06
  • 2021-04-06
  • 2021-10-11
  • 2010-11-22
  • 2013-10-07
  • 2013-04-04
  • 1970-01-01
相关资源
最近更新 更多