unsafe 到底解锁了什么?它有没有关掉借用检查?怎么把 unsafe 封装成安全接口?这篇逐条编译验证 unsafe 的边界,并写一个最小的安全抽象示范「前提条件检查 + 最小 unsafe 块」。
【解引用裸指针】编译失败:['error[E0133]: dereference of raw pointer is unsafe and requires unsafe block']
【调用 unsafe 函数】编译失败:['error[E0133]: call to unsafe function `danger` is unsafe and requires unsafe block']
【访问 static mut】编译失败:['error[E0133]: use of mutable static is unsafe and requires unsafe block']
【访问 union 字段】编译失败:['error[E0133]: access to union field is unsafe and requires unsafe block']
源码:
1 | unsafe trait Zeroable {}
2 | struct S; impl Zeroable for S {}
3 | fn main() {}
编译:失败
error[E0200]: the trait `Zeroable` requires an `unsafe impl` declaration
--> <实验目录>/src/u120b.rs:2:11
|
2 | struct S; impl Zeroable for S {}
| ^^^^^^^^^^^^^^^^^^^
|
= note: the trait `Zeroable` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
help: add `unsafe` to this trait implementation
|
2 | struct S; unsafe impl Zeroable for S {}
| ++++++
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0200`.裸指针的使用见原始指针解引用。
编译:成功;警告:
warning: trait `Zeroable` is never used
--> <实验目录>/src/u120c.rs:4:14
|
4 | unsafe trait Zeroable {} unsafe impl Zeroable for u32 {}
| ^^^^^^^^
|
= note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default
warning: 1 warning emitted
运行(退出码 0):
解引用裸指针 = 5
调用 unsafe fn = 5
static mut N = 1
union 字段 b = 1(把 u32 0x3f800000 当 f32 读)
unsafe impl Zeroable for u32:编译通过(实现 unsafe trait 本身也要写 unsafe impl) 源码:
1 | fn main() { let mut v = vec![1]; let first = &v[0]; unsafe { v.push(2); } println!("{}", first); }
编译:失败
warning: unnecessary `unsafe` block
--> <实验目录>/src/u120d.rs:1:53
|
1 | fn main() { let mut v = vec![1]; let first = &v[0]; unsafe { v.push(2); } println!("{}", first); }
| ^^^^^^ unnecessary `unsafe` block
|
= note: `#[warn(unused_unsafe)]` (part of `#[warn(unused)]`) on by default
error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
--> <实验目录>/src/u120d.rs:1:62
|
1 | fn main() { let mut v = vec![1]; let first = &v[0]; unsafe { v.push(2); } println!("{}", first); }
| - ^^^^^^^^^ ----- immutable borrow later used here
| | |
| | mutable borrow occurs here
| immutable borrow occurs here
error: aborting due to 1 previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0502`.借用规则见不可变借用与可变借用。
编译:成功
运行(退出码 101):
安全接口的结果:[10, 2, 30, 4, 5]
thread 'main' (7328087) panicked at <实验目录>/src/u120e.rs:3:5:
mid 必须 <= 长度
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace 源码:
1 | #![forbid(unsafe_code)]
2 | fn main() { let x = 1; let p = &x as *const i32; let _ = unsafe { *p }; }
编译:失败
error: usage of an `unsafe` block
--> <实验目录>/src/u120f.rs:2:58
|
2 | fn main() { let x = 1; let p = &x as *const i32; let _ = unsafe { *p }; }
| ^^^^^^^^^^^^^
|
note: the lint level is defined here
--> <实验目录>/src/u120f.rs:1:11
|
1 | #![forbid(unsafe_code)]
| ^^^^^^^^^^^
error: aborting due to 1 previous error
源码:
1 | unsafe fn f(p: *const i32) -> i32 { *p }
2 | fn main() { let x = 1; println!("{}", unsafe { f(&x) }); }
编译:成功;警告:
warning[E0133]: dereference of raw pointer is unsafe and requires unsafe block
--> <实验目录>/src/u120g.rs:1:37
|
1 | unsafe fn f(p: *const i32) -> i32 { *p }
| ^^ dereference of raw pointer
|
= note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
note: an unsafe function restricts its caller, but its body is safe by default
--> <实验目录>/src/u120g.rs:1:1
|
1 | unsafe fn f(p: *const i32) -> i32 { *p }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/unsafe-op-in-unsafe-fn.html>
= note: `#[warn(unsafe_op_in_unsafe_fn)]` (part of `#[warn(rust_2024_compatibility)]`) on by default
warning: 1 warning emitted
For more information about this error, try `rustc --explain E0133`.
运行(退出码 0):
1跨线程的 unsafe impl 见Send 与 Sync。