diff --git a/1.6/ja/book/unsafe.md b/1.6/ja/book/unsafe.md index 1b223365..3cc5a640 100644 --- a/1.6/ja/book/unsafe.md +++ b/1.6/ja/book/unsafe.md @@ -1,67 +1,125 @@ % Unsafe + +Rustの主たる魅力は、プログラムの動作についての強力で静的な保証です。 +しかしながら、安全性検査は本来保守的なものです。 +すなわち、実際には安全なのに、そのことがコンパイラには検証できないプログラムがいくらか存在します。 +その類のプログラムを書くためには、制約を少し緩和するようコンパイラに対して伝えることが要ります。 +そのために、Rustには `unsafe` というキーワードがあります。 +`unsafe` を使ったコードは、普通のコードよりも制約が少なくなります。 + + +まずシンタックスをみて、それからセマンティクスについて話しましょう。 +`unsafe` は4つの場面で使われます。 +1つめは、関数がアンセーフであることを印付ける場合です。 ```rust unsafe fn danger_will_robinson() { - // scary stuff +# // scary stuff + // 恐ろしいもの } ``` + +たとえば、[FFI][ffi]から呼び出されるすべての関数は`unsafe`で印付けることが必要です。 +`unsafe`の2つめの用途は、アンセーフブロックです。 [ffi]: ffi.html ```rust unsafe { - // scary stuff +# // scary stuff + // 恐ろしいもの } ``` -The third is for unsafe traits: + +3つめは、アンセーフトレイトです。 ```rust unsafe trait Scary { } ``` -And the fourth is for `impl`ementing one of those traits: + +そして、4つめは、そのアンセーフトレイトを実装する場合です。 ```rust # unsafe trait Scary { } unsafe impl Scary for i32 {} ``` + +大きな問題を引き起こすバグがあるかもしれないコードを明示できるのは重要なことです。 +もしRustのプログラムがセグメンテーション違反を起こしても、バグは `unsafe` で印付けられた区間のどこかにあると確信できます。 -# What does ‘safe’ mean? +# 「安全」とはどういう意味か? + + +Rustの文脈で、安全とは「どのようなアンセーフなこともしない」ことを意味します。 + +> 訳注: +正確には、安全とは「決して未定義動作を起こさない」ということです。 +そして、安全性が保証されていないことを「アンセーフ」と呼びます。 +つまり、未定義動作が起きるおそれがあるなら、それはアンセーフです。 +知っておくべき重要なことに、たいていのコードにおいて望ましくないが、アンセーフ _ではない_ とされている動作がいくらか存在するということがあります。 + + +* デッドロック +* メモリやその他のリソースのリーク +* デストラクタを呼び出さないプログラム終了 +* 整数オーバーフロー + +Rustはソフトウェアが抱えるすべての種類の問題を防げるわけではありません。 +Rustでバグのあるコードを書くことはできますし、実際に書かれるでしょう。 +これらの動作は良いことではありませんが、特にアンセーフだとは見なされません。 + +さらに、Rustにおいては、次のものは未定義動作で、 `unsafe` コード中であっても、避ける必要があります。 + +> 訳注: +関数に付いている`unsafe`は「その関数の処理はアンセーフである」ということを表します。 +その一方で、ブロックに付いている`unsafe`は「ブロック中の個々の操作はアンセーフだが、全体としては安全な処理である」ということを表します。 +避ける必要があるのは、未定義動作が起こりうる処理をアンセーフブロックの中に書くことです。 +それは、アンセーフブロックの処理が安全であるために、その内部で未定義動作が決して起こらないことが必要だからです。 +アンセーフ関数には安全性の保証が要らないので、未定義動作が起こりうるアンセーフ関数を定義することに問題はありません。 + +* データ競合 +* ヌル・ダングリング生ポインタの参照外し +* [undef][undef] (未初期化)メモリの読み出し +* 生ポインタによる [pointer aliasing rules][aliasing] の違反 +* `&mut T` と `&T` は、 `UnsafeCell` を含む `&T` を除き、LLVMのスコープ化された [noalias][noalias] モデルに従っています。アンセーフコードは、それら参照のエイリアシング保証を破ってはいけません。 +* `UnsafeCell` を持たないイミュータブルな値・参照の変更 +* コンパイラIntrinsic経由の未定義挙動の呼び出し + * `std::ptr::offset` (`offset` intrinsic) を使って、オブジェクトの範囲外を指すこと。ただし、オブジェクトの最後より1バイト後を指すことは許されている。 + * 範囲の重なったバッファに対して `std::ptr::copy_nonoverlapping_memory` (`memcpy32`/`memcpy64` + intrinsics) を使う +* プリミティブ型の不正な値(プライベートなフィールドやローカル変数を含む) + * ヌルかダングリングである参照やボックス + * `bool` における、 `false` (0) か `true` (1) でない値 + * `enum` の定義に含まれていない判別子 + * `char` における、サロゲートか `char::MAX` を超えた値 + * `str` における、UTF-8でないバイト列 +* 他言語からRustへの巻き戻しや、Rustから他言語への巻き戻し [noalias]: http://llvm.org/docs/LangRef.html#noalias [undef]: http://llvm.org/docs/LangRef.html#undefined-values [aliasing]: http://llvm.org/docs/LangRef.html#pointer-aliasing-rules -# Unsafe Superpowers +# アンセーフの能力 + + +アンセーフ関数・アンセーフブロックでは、Rustは普段できない3つのことをさせてくれます。たった3つです。それは、 + +1. [静的ミュータブル変数][static]のアクセスとアップデート。 +2. 生ポインタの参照外し。 +3. アンセーフ関数の呼び出し。これが最も強力な能力です。 + +以上です。 +重要なのは、 `unsafe` が、たとえば「借用チェッカをオフにする」といったことを行わないことです。 +Rustのコードの適当な位置に `unsafe` を加えてもセマンティクスは変わらず、何でもただ受理するようになるということにはなりません。 +それでも、`unsafe` はルールのいくつかを破るコードを書けるようにはするのです。 + +また、`unsafe` キーワードは、Rust以外の言語とのインターフェースを書くときに遭遇するでしょう。 +ライブラリの提供するメソッドの周りに、安全な、Rustネイティブのインターフェースを書くことが推奨されています。 + +これから、その基本的な3つの能力を順番に見ていきましょう。 -## Access or update a `static mut` +## `static mut` のアクセスとアップデート。 + + +Rustには「`static mut`」という、ミュータブルでグローバルな状態を実現する機能があります。 +これを使うことはデータレースが起こるおそれがあるので、本質的に安全ではありません。 +詳細は、この本の[static][static]セクションを参照してください。 [static]: const-and-static.html#static -## Dereference a raw pointer +## 生ポインタの参照外し + + +生ポインタによって任意のポインタ演算が可能になりますが、いくつもの異なるメモリ安全とセキュリティの問題が起こるおそれがあります。 +ある意味で、任意のポインタを参照外しする能力は行いうる操作のうち最も危険なもののひとつです。 +詳細は、[この本の生ポインタに関するセクション][rawpointers]を参照してください。 [rawpointers]: raw-pointers.html -## Call unsafe functions +## アンセーフ関数の呼び出し + + +この最後の能力は、`unsafe`の両面とともに働きます。 +すなわち、`unsafe`で印付けられた関数は、アンセーフブロックの内部からのみ呼び出すことができます。 + +この能力は強力で多彩です。 +Rustはいくらかの[compiler intrinsics][intrinsics]をアンセーフ関数として公開しており、また、いくつかのアンセーフ関数は安全性検査を回避することで、安全性とスピードを引き換えています。 + +繰り返しになりますが、アンセーフブロックと関数の内部で任意のことが _できる_ としても、それをすべきだということを意味しません。コンパイラは、あなたが不変量を守っているかのように動作しますから、注意してください! [intrinsics]: intrinsics.html diff --git a/TranslationTable.md b/TranslationTable.md index ab4603b7..4a490ef2 100644 --- a/TranslationTable.md +++ b/TranslationTable.md @@ -24,6 +24,7 @@ | block | ブロック | borrowing | 借用 | bounds | 境界 +| bug | バグ | channel | チャネル | capture | キャプチャ | closure | クロージャ @@ -36,11 +37,15 @@ | continuous integration | 継続的インテグレーション | crate | クレート | dangling | ダングリング +| data race | データ競合 +| deadlock | デッドロック | declaration statement | 宣言文 | dereferencing | 参照外し +| destructor | デストラクタ | destructuring | 分配 | directory | ディレクトリ | directive | ディレクティブ +| discriminant | 判別子 | distribution | 配布物 | diverge | ダイバージ | diverging | ダイバージング @@ -59,6 +64,7 @@ | hash | ハッシュ | identifier | 識別子 | immutable | イミュータブル +| implement | 実装する | initialize | 初期化する | input lifetime | 入力ライフタイム | install | インストール @@ -68,6 +74,7 @@ | keyword | キーワード | Intrinsics | Intrinsic | Lang Items | Lang Item +| leak | リーク | lending | 貸付け | library | ライブラリ | lifetime | ライフタイム @@ -83,11 +90,13 @@ | mutable | ミュータブル | mutability | ミュータビリティ | mutable binding | ミュータブルな束縛 +| null | ヌル | offline | オフライン | opaque | オペーク | open source | オープンソース | option | オプション | output lifetime | 出力ライフタイム +| overflow | オーバーフロー | owner | 所有者 | ownership | 所有権 | panic | パニック @@ -98,12 +107,16 @@ | platform | プラットフォーム | pointer | ポインタ | process | プロセス +| raw pointer | 生ポインタ | re-assignment | 再代入 | rebind | 再束縛 | regression | リグレッション | release | リリース | return | 返す +| safe | 安全 +| safety check | 安全性検査 | scope | スコープ +| scoped | スコープ化された | script | スクリプト | shadow | 覆い隠す | shadowing | シャドーイング @@ -129,6 +142,7 @@ | unsafe | アンセーフ | unsigned | 符号無し | unsized type | サイズ不定型 +| unwinding | 巻き戻し | variable | 変数 | variable binding | 変数束縛 | variant | ヴァリアント