做任务领黄钻的网站,seo推广培训费用,国外做化工网站,乐清建网站哪家强unsafe#xff1a;内存不安全 内存安全问题#xff0c;例如空指针解引用 关键字unsafe来切换到不安全模式#xff0c;并在被标记后的代码块中使用不安全代码 使用unsafe告诉编译器后面代码安全性自行负责 因为电脑硬件安全问题#xff0c;必须编写可能不安全的代码
可以将…unsafe内存不安全 内存安全问题例如空指针解引用 关键字unsafe来切换到不安全模式并在被标记后的代码块中使用不安全代码 使用unsafe告诉编译器后面代码安全性自行负责 因为电脑硬件安全问题必须编写可能不安全的代码
可以将不安全代码封装在一个安全的抽象中并提供一套安全的API防止unsafe代码泄漏到任何调用它的地方因为使用安全抽象总会是安全的。 不安全Rust允许你执行4种在安全Rust中不被允许的操作 解引用裸指针 裸指针 raw pointer裸指针要么是可变的要么是不可变的它们分别被写作*const T和*mut T固定写法。 星号是类型名的一部分而不是解引用操作。 裸指针使用裸指针的好处是可以规避Rust的引用规则 使用as语法创建裸指针并且创建裸指针不需要unsafe关键字 允许忽略借用规则可以同时拥有指向同一个内存地址的可变和 不可变指针或者拥有指向同一个地址的多个可变指针。 不能保证自己总是指向了有效的内存地址。 允许为空 没有实现任何自动清理机制 使用裸指针的目的要用途便是与C代码接口进行交互 调用不安全的函数或方法: 不安全函数unsafe function在定义前面要标记unsafe 单独的unsafe代码块中调用不安全的函数 你可以在一个不安全函数中执
行其他不安全操作而无须添加额外的unsafe代码块 创建不安全代码的安全抽象 将不安全代码封装在安全函数中是一种十分常见的抽象。 代码中如果需要两次可变引用那么就可以考虑使用裸指针 as_mut_ptr方法来访问切片包含的裸指针 slice::from_raw_parts_mut函数接收一个裸指针和长度来创建一个切片 ptr.offset()方法也是不安全的
fn split_at_mut(slice:mut [i32],mid:usize)-(mut [i32],mut [i32]){let len slice.len();let ptr slice.as_mut_ptr();// 可变指针assert!(midlen);unsafe{(slice::from_raw_parts_mut(ptr,mid),slice::from_raw_parts_mut(ptr.offset(mid as isize), len - mid)) } 使用裸指针关键是可以确认unsafe代码块中的裸指针都会指向有效的切片数据且不会产生任何的数据竞争 使用extern函数调用外部代码另一种语言 extern关键字, 简化创建使用外部函数的接口 任何在extern块中声明的函数都是不安全的。 extern C{fn abs(iput:i32) - i32;
} 声明在另一种语言中定义的函数 。C指明了外部函数使用的应用二进制接口 Application Binary InterfaceABI它被用来定义函数在汇编层面的调用方式。我们使用的CABI正是C编程语言的ABI它也是最常见的ABI格式之。 可以使用extern来创建一个允许其他语言调用Rust函数的接口。 #[no_mangle]
pub extern C fn call_from_c() {
println!(Just called a Rust function from C!);
} #[no_mangle] 告诉编译器不允许修改函数名 在“C”ABI后面指定函数名。这段代码可以被C语言使用 访问或修改可变的静态变量 如果两个线程同时访问一个可变的全局变量那么就会造成数据竞争。 全局变量也被称为静态 static变量 静态变量的名称会约定俗成地被写作SCREAMING_SNAKE_CASE 要标注变量的类型例如static str静态变量只能存储拥有static生命周期的引 用 常量和不可变静态变量静态变量的值在内存中拥有固定的地址使用它的值 总是会访问到同样的数据常量则允许在任何被使用到的时候复制其数据。 访问和修改可变的静态变量是不安全的 实现不安全trait trait定义的前面加上unsafe关键字该trait也只能在unsafe代码块中实现
总结unsafe关键字能够帮助轻松定位问题 tait的关联类型 定义出包含某些类型的trait而无须在实现前确定它们的具体类型是什么 pub trait Iterator{type Item;fn next(mut self) - OptionSelf::Item;
}impl Iterator for Counter {
type Item u32;
fn next(mut self) - OptionSelf::Item {
} Item就是trait的关联类型。关联类型和泛型很像 泛型版本
pub trait IteratorT {
fn next(mut self) - OptionT;
} 使用泛型需要在每次使用的时候指明泛型的具体类型
泛型也可以指明其他类型这样Counter就拥有多个不同版本的Iterator实现
impl IteratorString for Counter 在调用next的时候也必须指明具体的泛型类型 而使用关联类型
impl Iterator for Counter 不用每次都指定是哪种关联类型一次指定关联类型即可。 默认泛型参数和运算符重载 PlaceholderTypeConcreteType来为泛型指定默认类型。 运算符重载自定义运算符比如的具体行为。 完全限定语法 Rust既不会阻止两个trait拥有相同名称的方法也不会阻止你为同一个类型实现这样的两个trait。但是使用时需要具体指明调用的具体对象。 调用同名函数 let person Human;Pilot::fly(person);Wizard::fly(person);
然后传入实例的引用因为函数的第一个参数是self
那么对于关联函数第一个参数不是self 完全限定访问语法 Dog as Animal::baby_name() 超traitsuper trait 在一个trait中使用另外一个trait的功能 trait OutlinePrint: fmt::Display{
} 表明trait OutlinePrint依赖fmt::Display