裸指针和引用差在哪?什么时候需要它?这篇用小实验把裸指针的安全部分与 unsafe 部分分开验证:创建、比较、算术、别名、Box 往返,最后用它写一个会正确释放的双向链表。
编译:成功
运行(退出码 0):
创建裸指针不需要 unsafe;p == q(同一地址): true
null.is_null() = true p.is_null() = false
通过 *mut 修改后 *p = 15
悬空指针(指向已销毁的 y)创建不报错:地址 0x16f98e80c(解引用它是未定义行为,这里不解引用)unsafe 的边界见unsafe 的安全边界。
编译:成功
运行(退出码 0):
p.add(2) 指向 30(add 的单位是元素,u32 = 4 字节)
p.add(2) 比 p 大 8 字节
byte_add(4) 比 p 大 4 字节
q - p = 4 个元素(offset_from)
同样的 add(2),u8 数组:相差 2 字节 编译:成功
运行(退出码 0):
两个 *mut 都指向 x:修改后 x = 12(这里按顺序访问,没有同时读写,结果是确定的)
源码:
1 | fn main() { let mut x = 1; let a = &mut x; let b = &mut x; *a += 1; *b += 1; }
编译:失败
error[E0499]: cannot borrow `x` as mutable more than once at a time
--> <实验目录>/src/u121d.rs:1:52
|
1 | fn main() { let mut x = 1; let a = &mut x; let b = &mut x; *a += 1; *b += 1; }
| ------ ^^^^^^ ------- first borrow later used here
| | |
| | second mutable borrow occurs here
| first mutable borrow occurs here
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0499`. 编译:成功
运行(退出码 0):
into_raw 得到 0x105769300 —— 所有权交给了裸指针,Box 不会再 drop 它
from_raw 把 Noisy(2) 的所有权拿回来,离开作用域时正常 drop:
Noisy(2) drop
Noisy(1) 从未 from_raw:泄漏,永远不会有它的 drop 输出Box 的内存布局见Box、Rc、Arc 的内存布局。
编译:成功
运行(退出码 0):
正向 [10, 20, 30, 40] 反向 [40, 30, 20, 10] 长度 4
DList drop:释放了 4 个节点安全的引用计数方案见Weak<T> 解决循环引用。