陈天 · Rust 编程第一课
陈天
Tubi TV 研发副总裁
23195 人已学习
新⼈⾸单¥68
登录后,你可以任选4讲全文学习
课程目录
已完结/共 65 讲
基础篇 (21讲)
陈天 · Rust 编程第一课
15
15
1.0x
00:00/00:00
登录|注册

30|Unsafe Rust:如何用C++的方式打开Rust?

Other Unsafe Traits
Send / Sync Traits
Thought Exercise: Implementing split_mut() Function
Reflection on Learning
Importance of Understanding Unsafe Rust
Example: Implementing split() Function
Safety Requirements
Using Unsafe for Performance Optimization
Using Unsafe in Macros
Accessing or Modifying Mutable Static Variables
Using Foreign Function Interface (FFI)
Dereferencing Raw Pointers
Calling Existing Unsafe Functions
Implementing Unsafe Traits
Performance Optimization
Interfacing with Other Languages
Interacting with Unsafe Hardware
Limitations of Safe Rust
Rust's Memory Safety
Conclusion
Writing Unsafe Code
Not Recommended Scenarios for Using Unsafe Rust
Scenarios for Using Unsafe Rust
Reasons for Using Unsafe Rust
Introduction
Unsafe Rust

该思维导图由 AI 生成,仅供参考

你好,我是陈天。
到目前为止,我们撰写的代码都在 Rust 精心构造的内存安全的国度里做一个守法好公民。通过遵循所有权、借用检查、生命周期等规则,我们自己的代码一旦编译通过,就相当于信心满满地向全世界宣布:这个代码是安全的!
然而,安全的 Rust 并不能适应所有的使用场景。
首先,为了内存安全,Rust 所做的这些规则往往是普适性的,编译器会把一切可疑的行为都严格地制止掉。可是,这种一丝不苟的铁面无情往往会过于严苛,导致错杀。
就好比“屋子的主人只会使用钥匙开门,如果一个人尝试着撬门,那一定是坏人”,正常情况下,这个逻辑是成立的,所有尝试撬门的小偷,都会被抓获(编译错误);然而,有时候主人丢了钥匙,不得不请开锁匠开门(unsafe code),此时,是正常的诉求,是可以网开一面的。
其次,无论 Rust 将其内部的世界构建得多么纯粹和完美,它总归是要跟不纯粹也不完美的外界打交道,无论是硬件还是软件
计算机硬件本身是 unsafe 的,比如操作 IO 访问外设,或者使用汇编指令进行特殊操作(操作 GPU 或者使用 SSE 指令集)。这样的操作,编译器是无法保证内存安全的,所以我们需要 unsafe 来告诉编译器要法外开恩。
同样的,当 Rust 要访问其它语言比如 C/C++ 的库,因为它们并不满足 Rust 的安全性要求,这种跨语言的 FFI(Foreign Function Interface),也是 unsafe 的。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Rust语言中的unsafe代码是为了在需要时打开Rust的内存安全限制,主要用于处理硬件交互、跨语言调用和性能优化等情况。本文深入介绍了unsafe Rust的使用场景和注意事项,包括实现unsafe trait、调用已有的unsafe接口、对裸指针做解引用以及使用FFI。特别强调了实现Send/Sync trait时需要小心谨慎,避免出现程序崩溃的情况。文章还提到了不推荐的使用unsafe的场景,包括处理未初始化数据、访问可变静态变量、以及使用unsafe提升性能。此外,还介绍了如何撰写和调用unsafe代码时需要注意的安全性要求。总的来说,本文对于想要深入了解Rust语言内存安全特性的读者具有一定的参考价值。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《陈天 · Rust 编程第一课》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(8)

  • 最新
  • 精选
  • 罗杰
    先把safe rust 弄清楚,再考虑 unsafe 的事

    作者回复: 对!

    2021-11-05
    1
  • TheLudlows
    pub fn as_mut_ptr(&mut self) -> *mut u8 { self as *mut str as *mut u8 } 请问老师这个转换为什么要多一层 *mut str ,as *mut str 和 as *mut u8的区别是什么,还有说这个as 转换的过程做了什么

    作者回复: as 不会做什么,只是把一种类型当成另一种类型处理。第一个转换是把 &str 引用转换成对应的裸指针,第二个是把裸指针从一种类型转换成另一种类型。

    2021-11-16
  • D. D
    不能直接使用 get_unchecked_mut() 去实现,因为即使在 unsafe 代码里面也不能对一个变量同时进行多个可变借用,需要先转换成裸指针。 不知道这样实现可以吗? fn split_mut(s: &mut str, sep: char) -> Option<(&mut str, &mut str)> { let pos = s.find(sep); pos.map(|pos| { let len = s.len(); let sep_len = sep.len_utf8(); let ptr1: *mut u8 = s.as_mut_ptr(); let ptr2: *mut u8 = s[(pos + sep_len)..].as_mut_ptr(); unsafe { let s1 = std::slice::from_raw_parts_mut(ptr1, pos); let s2 = std::slice::from_raw_parts_mut(ptr2, len - (pos + sep_len)); (std::str::from_utf8_unchecked_mut(s1), std::str::from_utf8_unchecked_mut(s2)) } }) } https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=98493d711d7a002c318aace31ecb2af0

    作者回复: 嗯,是这个思路。用 ptr.add() 来处理指针会更好。参考代码见:https://github.com/tyrchen/geektime-rust/blob/master/30_unsafe/examples/split.rs#L26

    2021-11-06
  • 终生恻隐
    fn split_mut(s: &mut str, sep: char) -> Option<(&mut str, &mut str)> { let pos = s.find(sep); pos.map(|pos| unsafe { let len = s.len(); let sep_len = sep.len_utf8(); let ss = s.as_mut_ptr(); let mut scl = &mut *(slice_from_raw_parts_mut(ss, pos)); let mut scr = &mut *( slice_from_raw_parts_mut( ss.offset((pos + sep_len) as isize), len-(pos + sep_len) ) ); // println!("left {}", from_utf8_unchecked_mut(scl)); // println!("left {}", from_utf8_unchecked_mut(scr)); (from_utf8_unchecked_mut(scl), from_utf8_unchecked_mut(scr)) }) }

    作者回复: 嗯,思路是对的。参考代码:https://github.com/tyrchen/geektime-rust/blob/master/30_unsafe/examples/split.rs#L26

    2021-11-05
  • pedro
    因为 Send / Sync 是 auto trait,所以大部分情况下,你自己的数据结构不需要实现 Send / Sync,然而,当你在数据结构里使用裸指针时,因为裸指针是没有实现 Send/Sync 的,连带着你的数据结构也就没有实现 Send/Sync。但很可能你的结构是线程安全的,你也需要它线程安全。 但很可能你的结构是线程安全的,你也需要它线程安全? 这句话我咋理解不了啊,是线程安全的,咋还需要它线程安全?

    作者回复: 你如果可以保证它线程安全的话,需要实现 Send/Sync 告诉编译器它线程安全。否则编译器会报错。

    2021-11-05
    5
  • 杨学者
    let arr: [usize; 6] = unsafe { std::mem::transmute(map) }; 新版的rust1.72stable报错了,因为hashmap的源码更新了
    2023-09-02归属地:上海
  • 约书亚
    fn split_mut(s: &mut str, sep: char) -> Option<(&mut str, &mut str)> { let pos = s.find(sep); pos.map(|pos| { let len = s.len(); let sep_len = sep.len_utf8(); let p = s.as_mut_ptr(); unsafe { let s1 = from_raw_parts_mut(p, pos); let s2 = from_raw_parts_mut(p.add(pos + sep_len), len - pos - sep_len); (from_utf8_unchecked_mut(s1), from_utf8_unchecked_mut(s2)) } }) }
    2022-10-04归属地:德国
  • 进击的Lancelot
    关于思考题,我的实现: ```rust fn split_mut(s: &mut str, sep: char) -> Option<(&mut str, &mut str)> { let pos = s.find(sep); pos.map(|pos| { let len = s.len(); let sep_len = sep.len_utf8(); let s1 = s.get_mut(0..pos).unwrap().as_mut_ptr(); let s2 = s.get_mut(pos + sep_len..len).unwrap().as_mut_ptr(); unsafe { let s1 = from_raw_parts_mut(s1, pos); let s2 = from_raw_parts_mut(s2, len - pos - sep_len); (from_utf8_unchecked_mut(s1), from_utf8_unchecked_mut(s2)) } }) } ``` playground 连接: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=7be8e52e1278665816a03eb30fbfaf60
    2022-09-17归属地:广东
收起评论
显示
设置
留言
8
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部