我不明白为什么Box::new
没有返回Option
或Result
。
分配可能会失败,因为内存不是无限制的,或者其他可能发生的事情;这种情况下的行为是什么?我找不到任何有关它的信息。
答案 0 :(得分:31)
更通用的形式是内存不足(OOM)怎么办?
处理OOM有很多困难:
第一个问题是检测它。如今,许多操作系统默认使用交换空间。在这种情况下,在进入OOM情况之前,您的进程实际上遇到了麻烦,因为开始使用交换空间会显着减慢进程。当更高的进程需要更多的内存(OOM杀手)时,其他操作系统会杀死低优先级进程,或承诺比现有更多的内存,希望它不会被使用或在必要时可用(过度使用),等...
第二个问题是恢复。在进程级别,恢复的唯一方法是释放内存...而不是在平均时间内分配任何内存。这并不像听起来那么容易,例如,不能保证恐慌和退绕不需要分配内存(例如,如果不小心完成,存储恐慌消息的行为可以分配)。这就是aborts by default上当前的rustc运行时OOM。
第三个问题是语言集成:内存分配无处不在。使用Box
,Vec
,String
等等...所以,如果您避开恐慌路线并使用Result
路线,则需要调整几乎任何改变方法签名以解决这种类型的失败,这将在所有接口中冒泡。
最后,值得注意的是,在需要处理内存分配失败的域中......通常情况下,内存分配不允许开始。例如,在关键的嵌入式软件中,所有内存都是预先分配的,并且有一个证明,不会超过分配的内容。
这很重要,因为这意味着很少的情况,其中(1)允许动态内存分配,(2)必须由进程本身优雅地处理其失败。
在这一点上,人们只能想知道应该花费多少复杂性预算,以及这将推动99%不关心的程序的复杂程度。
答案 1 :(得分:9)
我发现Rust开发人员之间就liballoc中的某些低级函数没有返回Option
:PR #14230进行了以下通信。
特别是以下部分解释了其背后的一些原因:
<强> huonw 强>:
嗯...最低级别的库不应该触发任务 失败?我们是否计划让任何较低级别的图书馆返回 选项还是什么?
<强> alexcrichton 强>:
我发现想要触发任务失败是很常见的,远比我最初意识到的要多。我还发现所有情境都有某种形式或失败的概念,尽管它并不总是任务失败。
<强> huonw 强>:
我从任务失败的角度思考不能在呼叫站点恢复,即更高级别的库可以自由失败,但是绝对最低的构建块不应该,因此人们可以按照自己的意愿处理问题(即使它只是手动触发任务失败)。如果liballoc不是最低级别的分配库,那么失败就没问题了。 (顺便说一句,我想你可能误解了我的评论,因为我不是在谈论libcore,只是liballoc。)
<强> alexcrichton 强>:
哎呀,对不起!我相信核心分配器接口(位于liballoc中)将被指定为不会失败!(),只是它们之上的原语(例如,box运算符)。也许我们可以扩展框语法以允许返回选项一天以适应此用例,因为我非常希望能够重复使用此代码!
答案 2 :(得分:5)
这是一项语言设计决定。您不仅要考虑单个操作的逻辑(例如Box::new
),还要考虑它将如何影响语言的人体工程学。如果我们用Return
机制来处理内存分配错误,那么这些错误几乎会随处可见。即使该方法没有在堆当前上分配任何内存,它也可能在将来使用 。突然之间,由于您必须更改API,因此实施中的简单更改将被卡住,而语义版本控制意味着主要版本。所有这些都有一点好处,因为在存在交换和内存杀手的情况下,内存处理不是非常可靠或有用(通常你应该在内存不足错误之前就停止分配内存)。 / p>
我提出的一个解决方案是将内存不足视为恐慌,解除并终止相应的任务。
答案 3 :(得分:0)
对于来自 2021 年的人来说,linus 和你有同样的担忧。
<块引用>我确实认为“运行时故障恐慌”是一个基本问题。
希望这能通过 Rust 团队的影响来解决。
https://github.com/rust-lang/rust/pull/84266