第78回です。前回はこちら。
[第78回の様子]
2023/05/17に第78回を開催した。
内容としてはRust By Example 日本語版22. 安全でない操作の「22. 安全でない操作」、「22.1. Inline assembly」に取り組んだ。(22.1は途中まで...)
参加者は自分を入れて6人。ひさしぶりにドライバを担当した!
内容的にメモリ周りとか、アセンブリの話とかで、ちょうど今読んでいる本と近い内容なので興味深かった。
https://t.co/l16c0nZ5B5
— KIDANI Akito (@kdnakt) 2023年5月14日
ようやくChapter 6まで写経しつつ読んだ
あんまり理解できてる気がしないけど...
[学んだこと]
- 22. 安全でない操作
- アンセーフ、つまり安全でない操作について学んでいく
- ただし、アンセーフなコードは可能な限り小さくあるべき、と公式ドキュメントに書かれている
- Rustでは、コンパイラのチェックを避けるためにunsafe { ... }のブロックを利用する
- 用途は以下の通り
- 生ポインタはアスタリスク(*)で表す。参照(&T)が必ず有効なデータを指しているのに対し、生ポインタは安全でないのでunsafeブロックでしかデリファレンスを実行できない
fn main() { let raw_p: *const u32 = &10; unsafe { // デリファレンスした結果を比較 assert!(*raw_p == 10); } }
- 関数にunsafeをつけることができる:この場合、コンパイラが保証してくれないので、プログラマが正しさを保証する必要がある
- 以下では、std::slice::from_raw_parts()を例に説明する
use std::slice; fn main() { // u32の配列 let some_vector = vec![1, 2, 3, 4]; let pointer = some_vector.as_ptr(); let length = some_vector.len(); // 4 unsafe { // ポインタの位置からu32の配列として4要素分読む let my_slice: &[u32] = slice::from_raw_parts(pointer, length); assert_eq!(some_vector.as_slice(), my_slice); println!("{:?}", my_slice); // [1, 2, 3, 4] } }
- from_raw_parts()は、ポインタが有効であること、ポインタの指す値の型が正しいことを前提に動作する
- 呼び出す時の型を変えると、元の配列とは異なる値が得られる
use std::slice; fn main() { // 元のベクターの値を変更 let some_vector = vec![300, 2, 3, 4]; let pointer: *const u32 = some_vector.as_ptr(); let length = some_vector.len(); unsafe { // ポインタの型を合わせる let pointer2: *const u8 = pointer as *const u8; // u8のスライスとして読み込む let my_slice: &[u8] = slice::from_raw_parts(pointer2, length); println!("{:?}", my_slice); // [44, 1, 0, 0] // 解説:u32型で32ビットで保持されている300の値を、u8(8ビット)×4のスライスとして読み込んでいる // 実行環境がリトルエンディアンだったので、桁が小さい数字が先頭にきている // 44 + 256 x 1 = 300で元の値と一致している } }
- 22.1. Inline assembly
- Rustではasm!マクロを使って、アセンブリのコードを直接埋め込むことができる
- パフォーマンスやタイミングが必要な場合にどうぞ、ということらしい
- あるいはカーネルのコードなどハードウェアに近い部分でも必要とのこと
- 基本的な使い方は以下の通り
use std::arch::asm; unsafe { asm!("nop"); //何もしないアセンブリ命令 }
- asm!マクロは必ずunsafeブロックで実行する必要がある:Rustの借用チェッカが保証しているものを壊すこともできてしまうので。
[まとめ]
モブプログラミングスタイルでRust dojoを開催した。
Rustでインラインアセンブリ書けるのは分かったけど、書きたい人いるんだろうか...。
今週のプルリクエストはこちら。
もうちょっとでRust by Exampleが終わるので、そしたら次は関数型言語とかやってみようかしら。