不被视为 unsafe
的行为
Rust 编译器并不认为以下行为是非安全的,尽管程序员可能 (应该) 认为它们是不可取的、不符合预期或错误的。
死锁
内存和其他资源泄漏
退出时未调用析构函数
通过指针泄漏公开随机化的基址
整数溢出
如果程序出现算术溢出,那么程序员就犯了一个错误。 在下面的讨论中,算术溢出和算术环绕之间有的区别,前者是错误的,而后者是有意的。
当程序员启用了 debug_assert!
断言 (例如,启用了非优化构建) 时,实现必须插入动态检查以在溢出时引发 panic
。其他类型的构建可能会在溢出时导致 panics
或静默地环绕值,由实现自行决定。
在隐式环绕的情况下,实现必须使用二进制补码溢出约定提供明确定义的 (即使仍然被认为是错误的) 结果。
整数类型提供了固有方法,允许程序员显式地执行算术环绕。例如, i32::wrapping_add
提供了二进制补码的环绕加法。
标准库还提供了一个 Wrapping<T>
的新类型,它确保 T
的所有标准算术操作都具有环绕语义。
有关整数溢出的错误条件、原理和更多细节,请参见 RFC 560 。
逻辑错误
安全的代码可能会具有附加的逻辑约束,这些约束既无法在编译时检查,也无法在运行时检查。 如果程序违反了这些约束,则其行为可能是逻辑错误,但不会导致未定义行为。 这可能会包括恐慌、错误的结果、终止和非终端。 这种行为可能也会因为运行次数、构建方式或编译方式而不同。
例如,实现 Hash
和 Eq
都要求被认为相等的值具有相等的哈希值。
其一个例子是数据结构中,比如 BinaryHeap
、 BTreeMap
、 BTreeSet
、 HashMap
和 HashSet
,修改这些数据结构的键时有其约束。
如果违反约束则认为不是非安全的,但这时程序将产生错误,其行为不可预测。