为什么`box :: new`不返回`Option`或`Result`?

时间:2017-07-05 10:14:08

标签: rust runtime-error allocation

我不明白为什么Box::new没有返回OptionResult

分配可能会失败,因为内存不是无限制的,或者其他可能发生的事情;这种情况下的行为是什么?我找不到任何有关它的信息。

4 个答案:

答案 0 :(得分:31)

更通用的形式是内存不足(OOM)怎么办?

处理OOM有很多困难:

  • 检测到它,
  • 从中恢复(优雅地),
  • 将其整合到语言中(优雅地)。

第一个问题是检测它。如今,许多操作系统默认使用交换空间。在这种情况下,在进入OOM情况之前,您的进程实际上遇到了麻烦,因为开始使用交换空间会显着减慢进程。当更高的进程需要更多的内存(OOM杀手)时,其他操作系统会杀死低优先级进程,或承诺比现有更多的内存,希望它不会被使用或在必要时可用(过度使用),等...

第二个问题是恢复。在进程级别,恢复的唯一方法是释放内存...而不是在平均时间内分配任何内存。这并不像听起来那么容易,例如,不能保证恐慌和退绕不需要分配内存(例如,如果不小心完成,存储恐慌消息的行为可以分配)。这就是aborts by default上当前的rustc运行时OOM

第三个问题是语言集成:内存分配无处不在。使用BoxVecString等等...所以,如果您避开恐慌路线并使用Result路线,则需要调整几乎任何改变方法签名以解决这种类型的失败,这将在所有接口中冒泡。

最后,值得注意的是,在需要处理内存分配失败的域中......通常情况下,内存分配允许开始。例如,在关键的嵌入式软件中,所有内存都是预先分配的,并且有一个证明,不会超过分配的内容。

这很重要,因为这意味着很少的情况,其中(1)允许动态内存分配,(2)必须由进程本身优雅地处理其失败。

在这一点上,人们只能想知道应该花费多少复杂性预算,以及这将推动99%不关心的程序的复杂程度。

答案 1 :(得分:9)

我发现Rust开发人员之间就liballoc中的某些低级函数没有返回OptionPR #14230进行了以下通信。

特别是以下部分解释了其背后的一些原因:

<强> huonw

  

嗯...最低级别的库不应该触发任务   失败?我们是否计划让任何较低级别的图书馆返回   选项还是什么?

<强> alexcrichton

  

我发现想要触发任务失败是很常见的,远比我最初意识到的要多。我还发现所有情境都有某种形式或失败的概念,尽管它并不总是任务失败。

<强> huonw

  

我从任务失败的角度思考不能在呼叫站点恢复,即更高级别的库可以自由失败,但是绝对最低的构建块不应该,因此人们可以按照自己的意愿处理问题(即使它只是手动触发任务失败)。如果liballoc不是最低级别的分配库,那么失败就没问题了。 (顺便说一句,我想你可能误解了我的评论,因为我不是在谈论libcore,只是liballoc。)

<强> alexcrichton

  哎呀,对不起!我相信核心分配器接口(位于liballoc中)将被指定为不会失败!(),只是它们之上的原语(例如,box运算符)。

     

也许我们可以扩展框语法以允许返回选项一天以适应此用例,因为我非常希望能够重复使用此代码!

答案 2 :(得分:5)

这是一项语言设计决定。您不仅要考虑单个操作的逻辑(例如Box::new),还要考虑它将如何影响语言的人体工程学。如果我们用Return机制来处理内存分配错误,那么这些错误几乎会随处可见。即使该方法没有在堆当前上分配任何内存,它也可能在将来使用 。突然之间,由于您必须更改API,因此实施中的简单更改将被卡住,而语义版本控制意味着主要版本。所有这些都有一点好处,因为在存在交换和内存杀手的情况下,内存处理不是非常可靠或有用(通常你应该在内存不足错误之前就停止分配内存)。 / p>

主题讨论得很多on reddit

我提出的一个解决方案是将内存不足视为恐慌,解除并终止相应的任务。

答案 3 :(得分:0)

对于来自 2021 年的人来说,linus 和你有同样的担忧。

<块引用>

我确实认为“运行时故障恐慌”是一个基本问题。

希望这能通过 Rust 团队的影响来解决。

https://github.com/rust-lang/rust/pull/84266

https://lwn.net/ml/linux-kernel/YHdSATy9am21Tj4Z@localhost/

https://lkml.org/lkml/2021/4/14/1099