Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Rustってどんな言語

unisuke
November 20, 2022

 Rustってどんな言語

unisuke

November 20, 2022
Tweet

More Decks by unisuke

Other Decks in Technology

Transcript

  1. C++が安全でなくてRustが安全 っっっっっk っっs 1 std::vector<int> v { 10, 11 };

    2 int *vptr = &v[1]; 3 v.push_back(12); 4 std::cout << *vptr; C++
  2. C++が安全でなくてRustが安全 っっっっっk っっs 1 std::vector<int> v { 10, 11 };

    2 int *vptr = &v[1]; 3 v.push_back(12); 4 std::cout << *vptr; C++ Bug (use-after-free) result
  3. C++が安全でなくてRustが安全 っっっっっk 10 11 v 1 std::vector<int> v { 10,

    11 }; 2 int *vptr = &v[1]; 3 v.push_back(12); 4 std::cout << *vptr; C++
  4. C++が安全でなくてRustが安全 っっっっっk 10 11 v 1 std::vector<int> v { 10,

    11 }; 2 int *vptr = &v[1]; 3 v.push_back(12); 4 std::cout << *vptr; C++ vptr
  5. C++が安全でなくてRustが安全 っっっっっk 10 11 v 1 std::vector<int> v { 10,

    11 }; 2 int *vptr = &v[1]; 3 v.push_back(12); 4 std::cout << *vptr; C++ vptr 10 11 v 12
  6. C++が安全でなくてRustが安全 っっっっっk 10 11 v 1 std::vector<int> v { 10,

    11 }; 2 int *vptr = &v[1]; 3 v.push_back(12); 4 std::cout << *vptr; C++ vptr すでに解放済みのメモリ をさしている →ダングリングポインタ
  7. C++が安全でなくてRustが安全 っっっっっk っっs 1 let mut v = vec![10, 11];

    2 let vptr = &mut v[1]; 3 v.push(12); 4 println!("{}", *vptr); Rust
  8. C++が安全でなくてRustが安全 っっっっっk っっs 1 let mut v = vec![10, 11];

    2 let vptr = &mut v[1]; 3 v.push(12); 4 println!("{}", *vptr); Rust コンパイルエラー result
  9. 所有権システム っっっっっk let s1 = String::from("hello"); let s2 = s1;

    println!("s2 = {}", s2); //println!("s1 = {}", s1); Rust “hello” s1 所有者 • Rustの各値は、所有者と呼ばれる変数と対応している。 所有権の原則
  10. 所有権システム っっっっっk let s1 = String::from("hello"); let s2 = s1;

    println!("s2 = {}", s2); //println!("s1 = {}", s1); Rust “hello” s1 • いかなる時も所有者は一つである。 所有権の原則 s2 所有者
  11. 所有権システム っっっっっk let s1 = String::from("hello"); let s2 = s1;

    println!("s2 = {}", s2); //println!("s1 = {}", s1); Rust “hello” s1 s2 所有者 s2 = hello result
  12. 所有権システム っっっっっk let s1 = String::from("hello"); let s2 = s1;

    println!("s2 = {}", s2); println!("s1 = {}", s1); Rust “hello” s1 s2 所有者 コンパイルエラー(s1: value borrowed here after move) result
  13. 所有権システムのメリット っっっっっk • メモリに起因する問題を克服し てメモリ安全性が保証される • 解放忘れ/二重解放のトラブル がなくなる • 脆弱性の原因になる挙動を避け

    られる(ex. ダングリングポイ ンタ) vs 手動でメモリ管理 • ガベージコレクタの実行速度の 遅さ、メモリ効率というデメリ ットを克服する • 効率的で高速 vs ガベージコレクタ
  14. 所有権と関数 っっっっっk fn main() { let s1 = String::from("hello"); show_str(s1);

    println!("s1 = {}", s1); } fn show_str(str: String) { println!("{}", str); } Rust “hello” s1 str 所有者
  15. 所有権と関数 っっっっっk fn show_message(str: String) { println!("{}", str); } Rust

    “hello” s1 • 所有者がスコープから外れたら、値は破棄される。 所有権の原則 str 所有者 変数strがスコープ抜ける スコープ抜ける 破棄
  16. 所有権と関数 っっっっっk fn main() { let s1 = String::from("hello"); show_str(s1);

    println!("s1 = {}", s1); } Rust “hello” s1 破棄 コンパイルエラー(s1: value borrowed here after move) result
  17. 関数に渡した値を呼び出し元で再度使いたいとき① っっっっっk fn main() { let mut s1 = String::from("hello");

    s1 = show_str(s1); println!("s1 = {}", s1); } fn show_str(str: String) -> String { println!("{}", str); str } Rust “hello” s1 str 所有者
  18. 関数に渡した値を呼び出し元で再度使いたいとき① っっっっっk fn main() { let mut s1 = String::from("hello");

    s1 = show_str(s1); println!("s1 = {}", s1); } fn show_str(str: String) -> String { println!("{}", str); str } Rust “hello” s1 str 所有者
  19. 関数に渡した値を呼び出し元で再度使いたいとき① っっっっっk fn main() { let mut s1 = String::from("hello");

    s1 = show_str(s1); println!("s1 = {}", s1); } fn show_str(str: String) -> String { println!("{}", str); str } Rust s1 = hello result
  20. 関数に渡した値を呼び出し元で再度使いたいとき② っっっっっk fn main() { let s1 = String::from("hello"); show_str(&s1);

    println!("s1 = {}", s1); } fn show_str(str: &String) { println!("{}", str); } Rust “hello” s1 所有者
  21. 関数に渡した値を呼び出し元で再度使いたいとき② っっっっっk fn main() { let s1 = String::from("hello"); show_str(&s1);

    println!("s1 = {}", s1); } fn show_str(str: &String) { println!("{}", str); } Rust “hello” s1 str 所有者 s1の値を参照 所有権の移動は 発生しない
  22. 関数に渡した値を呼び出し元で再度使いたいとき② っっっっっk fn show_str(str: &String) { println!("{}", str); } Rust

    “hello” s1 str 所有者 s1の値を参照 所有権の移動は 発生しない 変数strがスコープ抜けるが、strは所有権を持た ないため、値は破棄されない
  23. 関数に渡した値を呼び出し元で再度使いたいとき② っっっっっk fn main() { let s1 = String::from("hello"); show_str(&s1);

    println!("s1 = {}", s1); } fn show_str(str: &String) { println!("{}", str); } Rust s1 = hello result
  24. 値を変更したいときは所有権持たせるしかない。。? っっっっっk fn main() { let s1 = String::from("hello"); show_str(&s1);

    println!("s1 = {}", s1); } fn show_str(str: &String) { str.push_str(" sample"); println!("{}", str); } Rust コンパイルエラー `str` is a `&` reference, so the data it refers to cannot be borrowed as mutable result
  25. 関数内で値を変更 っっっっっk fn main() { let mut s1 = String::from("hello");

    show_str(&mut s1); println!("s1 = {}", s1); } fn show_str(str: &mut String) { str.push_str(" sample"); println!("{}", str); } Rust hello sample s1 = hello sample result
  26. 可変参照 っっっっっk • 特定のスコープで、ある特定のデータに対しては、 一つしか可変な参 照を持てない • 不変な参照をしている間は、可変な参照をすることはできない 制約 1.

    2つ以上のポインタが同じデータに同時にアクセスする 2. 少なくとも一つのポインタがデータに書き込みを行っている 3. データへのアクセスを同期する機構が使用されていない データ競合が起こる条件 データ競合 を防ぐこと ができる
  27. C++が安全でなくてRustが安全 っっっっっk っっs 1 let mut v = vec![10, 11];

    2 let vptr = &mut v[1]; 3 v.push(12); 4 println!("{}", *vptr); Rust コンパイルエラー result
  28. ダングリングポインタをコンパイルエラーで防ぐ っっっっっk っっs fn sample() { let mut data: Vec<i32>

    = vec![10, 11]; // ↓ let vptr = &mut v[1]; let vptr : &'b i32 = Index::index::<'b>(&'b data, 0); // ↓ v.push(12); Vec::push(&'c mut data, 4) println!("{}", x); } Rust
  29. ダングリングポインタをコンパイルエラーで防ぐ っっっっっk っっs fn sample() { 1 let mut data:

    Vec<i32> = vec![10, 11]; 2 let x: &'b i32 = Index::index::<'b>(&'b data, 0); 3 Vec::push(&'c mut data, 4); 4 println!("{}", x); } Rust --------+'a | ----+'b | +'c | | ----+ | --------+
  30. ダングリングポインタをコンパイルエラーで防ぐ っっっっっk っっs fn sample() { 1 let mut data:

    Vec<i32> = vec![10, 11]; 2 let x: &'b i32 = Index::index::<'b>(&'b data, 0); 3 Vec::push(&'c mut data, 4); 4 println!("{}", x); } Rust --------+'a | ----+'b | +'c | | ----+ | --------+ xは'bで生存しなくてはいけない
  31. ダングリングポインタをコンパイルエラーで防ぐ っっっっっk っっs fn sample() { 1 let mut data:

    Vec<i32> = vec![10, 11]; 2 let x: &'b i32 = Index::index::<'b>(&'b data, 0); 3 Vec::push(&'c mut data, 4); 4 println!("{}", x); } Rust --------+'a | ----+’b | | | +‘c | | ----+ | --------+ xは'bで生存しなくてはいけない dataを参照する参照が’bで生存することを要求する
  32. 可変参照 っっっっっk • 特定のスコープで、ある特定のデータに対しては、 一つしか可変な参 照を持てない • 不変な参照をしている間は、可変な参照をすることはできない 制約 1.

    2つ以上のポインタが同じデータに同時にアクセスする 2. 少なくとも一つのポインタがデータに書き込みを行っている 3. データへのアクセスを同期する機構が使用されていない データ競合が起こる条件 データ競合 を防ぐこと ができる
  33. ダングリングポインタをコンパイルエラーで防ぐ っっっっっk っっs 不変な参照をしている間に可変な参照をすることはできないのでエラー fn sample() { 1 let mut

    data: Vec<i32> = vec![10, 11]; 2 let x: &'b i32 = Index::index::<'b>(&'b data, 0); 3 Vec::push(&'c mut data, 4); 4 println!("{}", x); } Rust --------+'a | ----+’b | | | +‘c | | ----+ | --------+ xは'bで生存しなくてはいけない dataを参照する参照が’bで生存することを要求する 新しい可変参照を生成⚠
  34. unsafe Rust っっっっっk • コンピュータのハードウェアが本質的にunsafeであるため、unsafeな処理 ができないと、特定の制御ができない • デバッグのため、unsafeブロックを小さくすることを推奨している • 生ポインタを参照外しすること

    • unsafeな関数やメソッドを呼ぶこと • 可変で静的な変数にアクセスしたり変更すること • unsafeなトレイトを実装すること unsafe superpowers(safe Rustでは行えない4つの行動)