不被视为 unsafe 的行为

Rust 编译器不会将以下行为视为不安全的,尽管程序员可能会(应该)发现它们是不可取的、意外的或错误的。

死锁
内存和其他资源泄漏
退出时不调用析构函数
通过指针泄漏暴露随机基地址
整数溢出

如果程序包含算术溢出,则表示程序员犯了一个错误。在下面的讨论中,我们将区分算术溢出和回绕算术。前者是错误的,而后者是有意的。

当程序员启用了 debug_assert! 断言时(例如,通过启用非优化构建),实现必须插入在溢出时 panic 的动态检查。其他类型的构建可能会导致 panic 或在溢出时静默地回绕值,具体取决于实现。

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

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

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

有关错误条件、基本原理和有关整数溢出的更多详细信息,请参阅 RFC 560

逻辑错误

安全代码可能会施加额外的逻辑约束,这些约束在编译时和运行时都无法检查。如果程序违反了此类约束,则行为可能未指定,但不会导致未定义的行为。这可能包括恐慌、错误结果、中止和非终止。不同运行、构建或构建类型之间的行为也可能有所不同。

例如,同时实现 HashEq 要求被视为相等的值具有相等的哈希值。另一个例子是 BinaryHeapBTreeMapBTreeSetHashMapHashSet 等数据结构,它们描述了对数据结构中的键进行修改时的约束。违反此类约束不被视为不安全,但程序被视为错误的,其行为不可预测。