【问题标题】:What happens in Rust programming language when an integer arithmetic operation overflows?当整数算术运算溢出时,Rust 编程语言会发生什么?
【发布时间】:2021-08-16 17:35:04
【问题描述】:

据我所知,在 C 编程语言(以及许多基于 C 的语言)中,当算术运算在 N 位整数上溢出时,此溢出会将结果缩短为 2 的 N 次方, 只保留结果的 LSB。

当这种整数算术运算在 Rust 编程语言中溢出时会发生什么。

【问题讨论】:

  • 您问题的第一句话并不是全部。 C 中的有符号整数溢出是未定义的行为,无符号溢出是以类型的最大值为模的(这不一定与您声称的相同,因为允许使用填充位)。

标签: rust integer-overflow


【解决方案1】:

当您在调试模式下编译时,Rust 会检查整数溢出,如果发生这种行为,会导致您的程序在运行时崩溃。

当您使用 --release 标志在发布模式下编译时,Rust 不包括对导致恐慌的整数溢出的检查。对于有符号值,结果基于二进制补码包装。对于无符号值,结果是类型的最大值 + 1 的模数。

标准库有许多函数可以更好地控制溢出情况下应该发生的情况,例如,checked_addwrapping_add 和其他一些变体。

如果您还没有,我建议您阅读The Rust Programming Language,其中有一个section 专门解决了这个问题。

【讨论】:

    【解决方案2】:

    来自Rust Reference, chapter "Behavior not considered unsafe"

    整数溢出

    如果程序包含算术溢出,则程序员犯了错误。在下面的讨论中,我们保持算术溢出和包装算术之间的区别。第一个是错误的,第二个是故意的。

    当程序员启用debug_assert! 断言(例如,通过启用非优化构建)时,实现必须插入动态检查panic 溢出。其他类型的构建可能会导致 panics 或溢出时静默包装的值,由实现自行决定。

    在隐式包装溢出的情况下,实现必须通过使用二进制补码溢出约定来提供定义明确的(即使仍被认为是错误的)结果。

    整数类型提供了允许程序员显式执行包装算术的固有方法。例如,i32::wrapping_add 提供二进制补码,环绕加法。

    标准库还提供了一个Wrapping<T> 新类型,它确保T 的所有标准算术运算都具有包装语义。

    请参阅RFC 560 了解错误情况、基本原理以及有关整数溢出的更多详细信息。

    因此,根据您的编译器设置,您的程序可能会在溢出时出现恐慌或静默换行。依赖于这些行为中的任何一个都不是一个好主意。如果您需要处理溢出的可能性,请使用包装函数明确告诉编译器您想要并期望溢出返回,或使用检查方法(如u32::checked_add)手动处理溢出。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-23
      • 2015-10-15
      • 2011-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多