|
|
@ -26,7 +26,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
人是会犯错误的,错误总会发生,不过通过要求这四类操作必须位于标记为 `unsafe` 的块中,就能够知道任何与内存安全相关的错误必定位于 `unsafe` 块内。保持 `unsafe` 块尽可能小,如此当之后调查内存 bug 时就会感谢你自己了。
|
|
|
|
人是会犯错误的,错误总会发生,不过通过要求这四类操作必须位于标记为 `unsafe` 的块中,就能够知道任何与内存安全相关的错误必定位于 `unsafe` 块内。保持 `unsafe` 块尽可能小,如此当之后调查内存 bug 时就会感谢你自己了。
|
|
|
|
|
|
|
|
|
|
|
|
为了尽可能隔离不安全代码,将不安全代码封装进一个安全的抽象并提供安全 API 是一个好主意,当我们学习不安全函数和方法时会讨论到。标准库的一部分被实现为在被评审过的不安全代码之上的安全抽象。这个计数防止了 `unsafe` 泄露到所有你或者用户希望使用由 `unsafe` 代码实现的功能的地方,因为使用其安全抽象是安全的。
|
|
|
|
为了尽可能隔离不安全代码,将不安全代码封装进一个安全的抽象并提供安全 API 是一个好主意,当我们学习不安全函数和方法时会讨论到。标准库的一部分被实现为在被评审过的不安全代码之上的安全抽象。这个技术防止了 `unsafe` 泄露到所有你或者用户希望使用由 `unsafe` 代码实现的功能的地方,因为使用其安全抽象是安全的。
|
|
|
|
|
|
|
|
|
|
|
|
让我们按顺序依次介绍上述四个超级力量,同时我们会看到一些提供不安全代码的安全接口的抽象。
|
|
|
|
让我们按顺序依次介绍上述四个超级力量,同时我们会看到一些提供不安全代码的安全接口的抽象。
|
|
|
|
|
|
|
|
|
|
|
@ -151,7 +151,7 @@ fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
|
|
|
|
|
|
|
|
|
|
|
|
此函数首先获取 slice 的长度,然后通过检查参数是否小于或等于这个长度来断言参数所给定的索引位于 slice 当中。该断言意味着如果传入的索引比要分割的 slice 的索引更大,此函数在尝试使用这个索引前 panic。
|
|
|
|
此函数首先获取 slice 的长度,然后通过检查参数是否小于或等于这个长度来断言参数所给定的索引位于 slice 当中。该断言意味着如果传入的索引比要分割的 slice 的索引更大,此函数在尝试使用这个索引前 panic。
|
|
|
|
|
|
|
|
|
|
|
|
次后我们在一个元组中返回两个可变的 slice:一个从原始 slice 的开头直到 `mid` 索引,另一个从 `mid` 直到原 slice 的结尾。
|
|
|
|
之后我们在一个元组中返回两个可变的 slice:一个从原始 slice 的开头直到 `mid` 索引,另一个从 `mid` 直到原 slice 的结尾。
|
|
|
|
|
|
|
|
|
|
|
|
如果尝试编译示例 19-5 的代码,会得到一个错误:
|
|
|
|
如果尝试编译示例 19-5 的代码,会得到一个错误:
|
|
|
|
|
|
|
|
|
|
|
@ -301,7 +301,7 @@ fn main() {
|
|
|
|
|
|
|
|
|
|
|
|
就像常规变量一样,我们使用 `mut` 关键来指定可变性。任何读写 `COUNTER` 的代码都必须位于 `unsafe` 块中。这段代码可以编译并如期打印出 `COUNTER: 3`,因为这是单线程的。拥有多个线程访问 `COUNTER` 则可能导致数据竞争。
|
|
|
|
就像常规变量一样,我们使用 `mut` 关键来指定可变性。任何读写 `COUNTER` 的代码都必须位于 `unsafe` 块中。这段代码可以编译并如期打印出 `COUNTER: 3`,因为这是单线程的。拥有多个线程访问 `COUNTER` 则可能导致数据竞争。
|
|
|
|
|
|
|
|
|
|
|
|
拥有可以全局访问的可变数据,难以保证不存在数据竞争,这就是为何 Rust 认为可变静态变量是不安全的。任何可能的情况,请优先使用第十六章讨论的并发技术和线程安全智能指针,这样编译器就能检测不同线程间的数据访问是安全的。
|
|
|
|
拥有可以全局访问的可变数据,难以保证不存在数据竞争,这就是为何 Rust 认为可变静态变量是不安全的。任何可能的情况,请优先使用第十六章讨论的并发技术和线程安全智能指针,这样编译器就能检测不同线程间的数据访问是否是安全的。
|
|
|
|
|
|
|
|
|
|
|
|
### 实现不安全 trait
|
|
|
|
### 实现不安全 trait
|
|
|
|
|
|
|
|
|
|
|
@ -325,7 +325,7 @@ unsafe impl Foo for i32 {
|
|
|
|
|
|
|
|
|
|
|
|
### 何时使用不安全代码
|
|
|
|
### 何时使用不安全代码
|
|
|
|
|
|
|
|
|
|
|
|
使用 `unsafe` 来进行这四个操作(超级力量)之一是没有问题的,甚至是不需要深思熟虑的,不过使得 `unsafe` 代码正确也实属不易因为编译器不能帮助保证内存安全。当有理由使用 `unsafe` 代码时,是可以这么做的,通过使用显式的 `unsafe` 标注使得在出现错误时易于追踪问题的源头。
|
|
|
|
使用 `unsafe` 来进行这四个操作(超级力量)之一是没有问题的,甚至是不需要深思熟虑的,不过使得 `unsafe` 代码正确也实属不易,因为编译器不能帮助保证内存安全。当有理由使用 `unsafe` 代码时,是可以这么做的,通过使用显式的 `unsafe` 标注使得在出现错误时易于追踪问题的源头。
|
|
|
|
|
|
|
|
|
|
|
|
[dangling-references]:
|
|
|
|
[dangling-references]:
|
|
|
|
ch04-02-references-and-borrowing.html#dangling-references
|
|
|
|
ch04-02-references-and-borrowing.html#dangling-references
|
|
|
|