Rust的安全保证是它的核心优势,但有时候你需要绕过这些检查:unsafe允许你执行Rust正常不允许的五种操作。这是Rust给高级开发者的"逃生舱口"。
fn main() {
// 1. 裸指针
let mut num = 5;
let r1 = &num as *const i32; // 不可变裸指针
let r2 = &mut num as *mut i32; // 可变裸指针
unsafe {
println!("r1指向: {}", *r1); // 解引用裸指针必须在unsafe中
*r2 = 10; // 通过裸指针修改
println!("修改后: {}", *r1);
}
// 2. unsafe函数
unsafe fn dangerous() -> i32 { 42 }
let result = unsafe { dangerous() };
println!("unsafe函数结果: {}", result);
// 3. 可变静态变量
static mut COUNTER: u32 = 0;
unsafe {
COUNTER += 1;
println!("计数器: {}", COUNTER);
}
// 4. split_at_mut的安全实现
fn split_at_mut(values: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
let len = values.len();
assert!(mid <= len);
// 安全: 两个切片不重叠
unsafe {
let ptr = values.as_mut_ptr();
(std::slice::from_raw_parts_mut(ptr, mid),
std::slice::from_raw_parts_mut(ptr.add(mid), len - mid))
}
}
let mut arr = [1, 2, 3, 4, 5, 6];
let (left, right) = split_at_mut(&mut arr, 3);
println!("左: {:?}, 右: {:?}", left, right);
}
✅ 验证通过
use std::ptr::NonNull;
struct MyVec<T> {
ptr: NonNull<T>,
len: usize,
capacity: usize,
}
impl<T> MyVec<T> {
fn new() -> Self {
MyVec { ptr: NonNull::dangling(), len: 0, capacity: 0 }
}
fn with_capacity(capacity: usize) -> Self {
if capacity == 0 {
return Self::new();
}
let ptr = unsafe {
let layout = std::alloc::Layout::array::(capacity).unwrap();
let ptr = std::alloc::alloc(layout) as *mut T;
NonNull::new(ptr).expect("分配失败")
};
MyVec { ptr, len: 0, capacity }
}
fn push(&mut self, value: T) {
assert!(self.len < self.capacity, "容量已满");
unsafe {
std::ptr::write(self.ptr.as_ptr().add(self.len), value);
}
self.len += 1;
}
fn get(&self, index: usize) -> Option<&T> {
if index < self.len {
unsafe { Some(&*self.ptr.as_ptr().add(index)) }
} else {
None
}
}
fn len(&self) -> usize { self.len }
}
impl<T> Drop for MyVec<T> {
fn drop(&mut self) {
if self.capacity > 0 {
unsafe {
for i in 0..self.len {
std::ptr::drop_in_place(self.ptr.as_ptr().add(i));
}
let layout = std::alloc::Layout::array::(self.capacity).unwrap();
std::alloc::dealloc(self.ptr.as_ptr() as *mut u8, layout);
}
}
}
}
fn main() {
let mut v: MyVec<i32> = MyVec::with_capacity(5);
v.push(10); v.push(20); v.push(30);
for i in 0..v.len() {
println!("v[{}] = {}", i, v.get(i).unwrap());
}
}
✅ 验证通过
使用裸指针实现FNV-1a哈希函数,比较与标准库的性能。
使用Pin和裸指针安全地实现自引用结构体。
pub struct SafeSplit<'a, T> {
first: &'a mut [T],
second: &'a mut [T],
}
impl<'a, T> SafeSplit<'a, T> {
pub fn new(slice: &'a mut [T], mid: usize) -> Option {
if mid > slice.len() { return None; }
let ptr = slice.as_mut_ptr();
let len = slice.len();
unsafe {
Some(SafeSplit {
first: std::slice::from_raw_parts_mut(ptr, mid),
second: std::slice::from_raw_parts_mut(ptr.add(mid), len - mid),
})
}
}
}
fn main() {
let mut arr = [1, 2, 3, 4, 5, 6];
let split = SafeSplit::new(&mut arr, 3).unwrap();
println!("左: {:?}, 右: {:?}", split.first, split.second);
println!("unsafe安全封装: 内部unsafe,外部安全API");
}
✅ 验证通过
// 需要unsafe的场景:
// 1. FFI(调用C代码) → 必须
// 2. 裸指针解引用 → 必须
// 3. 可变静态变量 → 必须
// 4. 性能关键路径(避免边界检查) → 可选但需benchmark
// 5. 实现底层数据结构 → 必须
//
// 不需要unsafe的替代方案:
// • 边界检查 → 使用get()/get_mut()而非[]
// • 类型转换 → 使用From/TryFrom
// • 并发 → 使用Arc/Mutex/Channel
// • 可变性 → 使用RefCell
fn main() {
// 安全的替代方案
let v = vec![1, 2, 3];
// ❌ 不安全: v[100] 可能panic
// ✅ 安全: v.get(100) 返回None
match v.get(100) {
Some(val) => println!("值: {}", val),
None => println!("索引越界,安全处理"),
}
// unsafe的安全封装原则
println!("
unsafe安全封装原则:");
println!("1. unsafe块尽量小");
println!("2. 封装为安全的公开API");
println!("3. 在文档中说明安全条件");
println!("4. 使用SAFETY注释标记安全推理");
// SAFETY: 标准库中的安全注释模式
// // SAFETY: `ptr` is valid for `len` elements because ...
// unsafe { std::slice::from_raw_parts(ptr, len) }
}
✅ 验证通过
use std::ptr::NonNull;
struct MyVec {
ptr: NonNull,
len: usize,
capacity: usize,
}
impl MyVec {
fn new() -> Self {
MyVec { ptr: NonNull::dangling(), len: 0, capacity: 0 }
}
fn with_capacity(capacity: usize) -> Self {
if capacity == 0 { return Self::new(); }
let ptr = unsafe {
let layout = std::alloc::Layout::array::(capacity).unwrap();
let p = std::alloc::alloc(layout) as *mut T;
NonNull::new(p).expect("allocation failed")
};
MyVec { ptr, len: 0, capacity }
}
fn push(&mut self, value: T) {
assert!(self.len < self.capacity, "capacity exceeded");
unsafe { std::ptr::write(self.ptr.as_ptr().add(self.len), value); }
self.len += 1;
}
fn get(&self, i: usize) -> Option<&T> {
if i < self.len { unsafe { Some(&*self.ptr.as_ptr().add(i)) } } else { None }
}
fn len(&self) -> usize { self.len }
}
impl Drop for MyVec {
fn drop(&mut self) {
if self.capacity > 0 {
unsafe {
for i in 0..self.len { std::ptr::drop_in_place(self.ptr.as_ptr().add(i)); }
let layout = std::alloc::Layout::array::(self.capacity).unwrap();
std::alloc::dealloc(self.ptr.as_ptr() as *mut u8, layout);
}
}
}
}
fn main() {
let mut v: MyVec = MyVec::with_capacity(5);
v.push("Hello".to_string());
v.push("Rust".to_string());
v.push("unsafe".to_string());
for i in 0..v.len() { println!("v[{}] = {}", i, v.get(i).unwrap()); }
}
✅ 验证通过
// Miri: Rust未定义行为检测器
// rustup toolchain install nightly
// cargo +nightly miri test
// 检测: 内存越界、悬垂指针、数据竞争、未初始化内存
fn main() {
// Miri可以检测的错误:
println!("Miri检测范围:");
println!(" ✅ 越界内存访问");
println!(" ✅ 使用已释放内存");
println!(" ✅ 数据竞争");
println!(" ✅ 整数溢出(未检查)");
println!(" ✅ 无效引用");
println!("
安全替代方案优先:");
println!(" get_unchecked → get()");
println!(" unsafe零拷贝 → clone()");
println!(" 裸指针 → 引用");
println!(" unsafe fn → 返回Result");
println!("
标准库中的unsafe用法:");
println!(" Vec::push - 可能重新分配");
println!(" String::from_utf8_unchecked - 跳过验证");
println!(" slice::from_raw_parts - 裸指针转切片");
}
use std::mem;
// 零拷贝网络包解析
#[repr(C, packed)]
struct IpHeader {
version_ihl: u8,
tos: u8,
total_length: u16,
identification: u16,
flags_fragment: u16,
ttl: u8,
protocol: u8,
checksum: u16,
src_addr: [u8; 4],
dst_addr: [u8; 4],
}
impl IpHeader {
fn version(&self) -> u8 { self.version_ihl >> 4 }
fn header_length(&self) -> u8 { (self.version_ihl & 0x0F) * 4 }
fn total_length(&self) -> u16 { u16::from_be(self.total_length) }
fn ttl(&self) -> u8 { self.ttl }
fn protocol(&self) -> u8 { self.protocol }
fn src(&self) -> String { format!("{}.{}.{}.{}", self.src_addr[0], self.src_addr[1], self.src_addr[2], self.src_addr[3]) }
fn dst(&self) -> String { format!("{}.{}.{}.{}", self.dst_addr[0], self.dst_addr[1], self.dst_addr[2], self.dst_addr[3]) }
}
fn parse_ip_packet(data: &[u8]) -> Option<&IpHeader> {
if data.len() < mem::size_of::() { return None; }
let ptr = data.as_ptr() as *const IpHeader;
unsafe {
let header = &*ptr;
if header.version() != 4 { return None; }
Some(header)
}
}
fn main() {
let mut packet = vec![0u8; 20];
packet[0] = 0x45; // IPv4, 20字节头
packet[1] = 0x00; // TOS
packet[2] = 0x00; packet[3] = 0x28; // 总长40
packet[8] = 64; // TTL
packet[9] = 6; // TCP
packet[12..16].copy_from_slice(&[192, 168, 1, 1]); // 源地址
packet[16..20].copy_from_slice(&[10, 0, 0, 1]); // 目标地址
if let Some(header) = parse_ip_packet(&packet) {
println!("IP包解析:");
println!(" 版本: IPv{}", header.version());
println!(" 头长度: {}字节", header.header_length());
println!(" TTL: {}", header.ttl());
println!(" 协议: {} ({})", header.protocol(), if header.protocol()==6{"TCP"}else{"UDP"});
println!(" 源: {}", header.src());
println!(" 目标: {}", header.dst());
}
}
✅ 验证通过