
概述Rust 中的 unsafe 关键字 用于标记哪些编译器无法完全验证安全性的代码。它允许你执行一些通常被 Rust 的安全规则禁止的操作但同时要求程序员自己确保这些操作的安全性什么是 unsafe unsafe 不意味着代码一定危险而是意味着:编译器无法自动验证这段代码的内存安全性程序员需要手动确保代码符合Rust 的安全约定允许访问一些通常被禁止的低级功能例子unsafe 允许的五大操作解引用裸指针调用不安全函数访问和修改可变静态变量实现不安全 trait访问联合体字段解引用裸指针Unsafe: 直接通过裸指针读取或写入数据fnunsafe_raw_pointer(){letx10;lety20;// 创建裸指针是安全的letraw_ptr1xas*consti32;letraw_ptr2yas*consti32;unsafe{// 解引用裸指针需要 unsafeletvalue1*raw_ptr1;letvalue2*raw_ptr2;println!(Unsafe: {} {} {},value1,value2,value1value2);}}safe: 使用引用和mut由编译器检查生命周期和借用规则fnsafe_references(){letx10;lety20;// 使用引用编译器会验证安全性letref1x;letref2y;// 直接解引用编译器保证安全letvalue1*ref1;letvalue2*ref2;println!(Safe: {} {} {},value1,value2,value1value2);// 或者更简洁的方式println!(Safe simpler: {} {} {},x,y,xy);}调用不安全函数unsafe: 调用被标记为unsafe的函数// 声明不安全函数unsafefndangerous_function(buffer:*mut[u8;1024]){if!buffer.is_null(){// 直接操作内存(*buffer)[0]42;}}fncall_unsafe(){letmutdata[0u8;1024];unsafe{dangerous_function(mutdataas*mut[u8;1024]);}println!(Unsafe result: {},data[0]);}safe: 调用safe函数或者通过安全封装后的函数内部可能包含unsafe但对外是safe的接口// 安全函数声明fnsafe_function(buffer:mut[u8;1024]){// 使用安全的索引访问buffer[0]42;}fncall_safe(){letmutdata[0u8;1024];// 直接调用无需 unsafesafe_function(mutdata);println!(Safe result: {},data[0]);}访问和修改可变静态变量unsafe: 直接读写可变静态变量static mutstaticmutGLOBAL_COUNTER:u320;fnunsafe_global_modification(){unsafe{GLOBAL_COUNTER1;println!(Unsafe global: {},GLOBAL_COUNTER);}}safe: 使用原子类型或者通过Mutex等同步机制来安全地共享可变状态usestd::sync::atomic::{AtomicU32,Ordering};usestd::sync::Mutex;// 使用原子操作staticSAFE_COUNTER:AtomicU32AtomicU32::new(0);// 或者使用互斥锁staticSAFE_DATA:MutexVecStringMutex::new(Vec::new());fnsafe_global_modification(){// 原子操作 - 线程安全且无需 unsafeletcountSAFE_COUNTER.fetch_add(1,Ordering::SeqCst);println!(Safe atomic: {},count1);// 互斥锁保护 - 线程安全{letmutdataSAFE_DATA.lock().unwrap();data.push(hello.to_string());}}实现不安全traitunsafe: 实现一个被标记为unsafe的trait// 不安全 trait实现者必须保证某些不变量unsafetraitUnsafeSend:Send{// 实现者必须保证这个类型可以安全地跨线程发送}unsafeimplUnsafeSendfori32{// 我们知道 i32 可以安全发送}structMyUnsafeType{data:*mutu8,}unsafeimplSendforMyUnsafeType{// 手动保证这个类型可以安全发送}safe: 实现普通的trait。// 安全 trait编译器会自动验证安全性traitSafeTrait{fndo_something(self);}// 自动推导的 trait 实现#[derive(Clone, Debug)]structMySafeType{data:Vecu8,}implSafeTraitforMySafeType{fndo_something(self){println!(Safe trait implementation);}}// 自动实现 Send 和 Sync因为所有字段都实现了这些 trait// 编译器自动验证无需手动保证访问联合体字段unsafe: 访问Rust联合体union的字段#[repr(C)]unionMyUnion{integer:u32,float:f32,bytes:[u8;4],}fnunsafe_union_access(){letuMyUnion{integer:0x40490FDB};// PI 的 IEEE 754 表示unsafe{// 访问联合体字段需要 unsafeprintln!(Unsafe union - as integer: {},u.integer);println!(Unsafe union - as float: {},u.float);println!(Unsafe union - as bytes: {:?},u.bytes);}}safe: 使用枚举enum或者结构体struct来避免直接访问联合体// 使用枚举替代联合体enumSafeVariant{Integer(u32),Float(f32),Bytes([u8;4]),}implSafeVariant{fnas_integer(self)-Optionu32{matchself{SafeVariant::Integer(i)Some(*i),_None,}}fnas_float(self)-Optionf32{matchself{SafeVariant::Float(f)Some(*f),_None,}}fnas_bytes(self)-Option[u8;4]{matchself{SafeVariant::Bytes(b)Some(*b),_None,}}}fnsafe_enum_access(){letvariantSafeVariant::Integer(0x40490FDB);// 安全访问类型安全ifletSome(int_val)variant.as_integer(){println!(Safe enum - as integer: {},int_val);}// 或者使用模式匹配matchvariant{SafeVariant::Integer(i)println!(Matched integer: {},i),SafeVariant::Float(f)println!(Matched float: {},f),SafeVariant::Bytes(b)println!(Matched bytes: {:?},b),}}