不被视为 unsafe 的行为

Rust 编译器并不认为以下行为是非安全的,尽管程序员可能 (应该) 认为它们是不可取的、不符合预期或错误的。

死锁
内存和其他资源泄漏
退出时未调用析构函数
通过指针泄漏公开随机化的基址
整数溢出

如果程序出现算术溢出,那么程序员就犯了一个错误。 在下面的讨论中,算术溢出和算术环绕之间有的区别,前者是错误的,而后者是有意的。

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

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

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

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

有关整数溢出的错误条件、原理和更多细节,请参见 RFC 560

逻辑错误

安全的代码可能会具有附加的逻辑约束,这些约束既无法在编译时检查,也无法在运行时检查。 如果程序违反了这些约束,则其行为可能是逻辑错误,但不会导致未定义行为。 这可能会包括恐慌、错误的结果、终止和非终端。 这种行为可能也会因为运行次数、构建方式或编译方式而不同。

例如,实现 HashEq 都要求被认为相等的值具有相等的哈希值。 其一个例子是数据结构中,比如 BinaryHeapBTreeMapBTreeSetHashMapHashSet ,修改这些数据结构的键时有其约束。 如果违反约束则认为不是非安全的,但这时程序将产生错误,其行为不可预测。