1+ <!--
12# Unchecked Uninitialized Memory
3+ -->
24
5+ # チェックされない初期化されていないメモリ
6+
7+ <!--
38One interesting exception to this rule is working with arrays. Safe Rust doesn't
49permit you to partially initialize an array. When you initialize an array, you
510can either set every value to the same thing with `let x = [val; N]`, or you can
611specify each member individually with `let x = [val1, val2, val3]`.
712Unfortunately this is pretty rigid, especially if you need to initialize your
813array in a more incremental or dynamic way.
14+ -->
15+
16+ この規則の興味深い例外に、配列があります。安全な Rust は、配列を部分的に初期化することを
17+ 認めません。配列を初期化するとき、 ` let x = [val; N] ` を用いて
18+ 全ての値を初期化するか、 ` let x = [val1, val2, val3] ` を用いて、
19+ それぞれの要素の値を個別に指定するかのどちらかが出来ます。残念ながら、
20+ 特によりインクリメンタルなやり方や、動的な方法で配列を初期化する必要がある場合、
21+ これは非常に融通が利きません。
922
23+ <!--
1024Unsafe Rust gives us a powerful tool to handle this problem:
1125`mem::uninitialized`. This function pretends to return a value when really
1226it does nothing at all. Using it, we can convince Rust that we have initialized
1327a variable, allowing us to do trickier things with conditional and incremental
1428initialization.
29+ -->
30+
31+ アンセーフな Rust では、この問題に対処するパワフルなツールが用意されています。 ` mem::uninitialized ` です。
32+ この関数は本当に何もせず、値を返すふりをします。これを利用することで、 Rust に
33+ 変数が初期化されたと見なさせることができ、状況に応じた、インクリメンタルな初期化を
34+ 行ないトリッキーなことが出来ます。
1535
36+ <!--
1637Unfortunately, this opens us up to all kinds of problems. Assignment has a
1738different meaning to Rust based on whether it believes that a variable is
1839initialized or not. If it's believed uninitialized, then Rust will semantically
1940just memcopy the bits over the uninitialized ones, and do nothing else. However
2041if Rust believes a value to be initialized, it will try to `Drop` the old value!
2142Since we've tricked Rust into believing that the value is initialized, we can no
2243longer safely use normal assignment.
44+ -->
2345
46+ 残念ながら、これによってあらゆる種類の問題が浮かび上がります。
47+ 変数が初期化されていると Rust が思っているか、思っていないかによって、
48+ 代入は異なる意味を持ちます。もし初期化していないと思っている場合、 Rust は、
49+ セマンティクス的には単にビットを初期化していないメモリにコピーし、他には
50+ 何もしません。しかし、もし値が初期化していると思っている場合、 Rust は
51+ 古い値を ` Drop ` しようとします! Rust に、値が初期化されていると信じ込ませるよう
52+ トリックをしたので、もはや安全には普通の代入は使えません。
53+
54+ <!--
2455This is also a problem if you're working with a raw system allocator, which
2556returns a pointer to uninitialized memory.
57+ -->
58+
59+ 生のシステムアロケータを使用している場合も問題となります。このアロケータは、
60+ 初期化されていないメモリへのポインタを返すからです。
2661
62+ <!--
2763To handle this, we must use the `ptr` module. In particular, it provides
2864three functions that allow us to assign bytes to a location in memory without
2965dropping the old value: `write`, `copy`, and `copy_nonoverlapping`.
66+ -->
67+
68+ これに対処するには、 ` ptr ` モジュールを使用しなければなりません。
69+ 特にこのモジュールは、古い値をドロップせずに、メモリ上の場所に値を代入することが
70+ 可能となる 3 つの関数を提供しています: ` write ` 、` copy ` 、` copy_nonoverlapping ` です。
3071
72+ <!--
3173* `ptr::write(ptr, val)` takes a `val` and moves it into the address pointed
3274 to by `ptr`.
3375* `ptr::copy(src, dest, count)` copies the bits that `count` T's would occupy
@@ -36,50 +78,90 @@ dropping the old value: `write`, `copy`, and `copy_nonoverlapping`.
3678* `ptr::copy_nonoverlapping(src, dest, count)` does what `copy` does, but a
3779 little faster on the assumption that the two ranges of memory don't overlap.
3880 (this is equivalent to memcpy -- note that the argument order is reversed!)
81+ -->
3982
83+ * ` ptr::write(ptr, val) ` は ` val ` を受け取り、 ` ptr ` が指し示すアドレスに受け取った値を
84+ 移します。
85+ * ` ptr::copy(src, dest, count) ` は、 T 型の ` count ` が占有するビット数だけ、 src から dest に
86+ コピーします。 (これは memmove と同じです -- 引数の順序が逆転していることに注意してください!)
87+ * ` ptr::copy_nonoverlapping(src, dest, count) ` は ` copy ` と同じことをしますが、 2 つのメモリ領域が
88+ 重なっていないと見なしているため、若干高速です。 (これは memcpy と同じです -- 引数の
89+ 順序が逆転していることに注意してください!)
90+
91+ <!--
4092It should go without saying that these functions, if misused, will cause serious
4193havoc or just straight up Undefined Behavior. The only things that these
4294functions *themselves* require is that the locations you want to read and write
4395are allocated. However the ways writing arbitrary bits to arbitrary
4496locations of memory can break things are basically uncountable!
97+ -->
98+
99+ 言うまでもないのですが、もしこれらの関数が誤用されると、甚大な被害を引き起こしたり、
100+ 未定義動作を引き起こすでしょう。これらの関数* 自体* が必要とする唯一のものは、
101+ 読み書きしたい場所がアロケートされているということです。しかし、
102+ 任意のビットを任意のメモリの場所に書き込むことでものを壊すようなやり方は数え切れません!
45103
104+ <!--
46105Putting this all together, we get the following:
106+ -->
107+
108+ これらを全部一緒にすると、以下のようなコードとなります。
47109
48110``` rust
49111use std :: mem;
50112use std :: ptr;
51113
52- // size of the array is hard-coded but easy to change. This means we can't
53- // use [a, b, c] syntax to initialize the array, though !
114+ // 配列の大きさはハードコードされていますが,簡単に変えられます。
115+ // これは、配列を初期化するのに [a, b, c] という構文を使えないことを意味しますがね !
54116const SIZE : usize = 10 ;
55117
56118let mut x : [Box <u32 >; SIZE ];
57119
58120unsafe {
59- // convince Rust that x is Totally Initialized
121+ // Rust に x が完全に初期化されたと思わせます
60122 x = mem :: uninitialized ();
61123 for i in 0 .. SIZE {
62- // very carefully overwrite each index without reading it
63- // NOTE: exception safety is not a concern; Box can't panic
124+ // 非常に注意深く、それぞれのインデックスを読み込まずに上書きします
125+ // 注意: 例外安全性は考慮されていません。 Box はパニックできません
64126 ptr :: write (& mut x [i ], Box :: new (i as u32 ));
65127 }
66128}
67129
68130println! (" {:?}" , x );
69131```
70132
133+ <!--
71134It's worth noting that you don't need to worry about `ptr::write`-style
72135shenanigans with types which don't implement `Drop` or contain `Drop` types,
73136because Rust knows not to try to drop them. Similarly you should be able to
74137assign to fields of partially initialized structs directly if those fields don't
75138contain any `Drop` types.
139+ -->
76140
141+ ` Drop ` を実装していない型や、 ` Drop ` を実装する型を含まない型との、` ptr::write ` スタイルの
142+ いたずらを心配しなくてよいということは注目に値します。なぜなら Rust は、これらをドロップしようと
143+ しないと知っているからです。同じように、もし部分的に初期化されている構造体のフィールドに ` Drop ` を
144+ 実装しているものが存在しない場合、このフィールド群に直接代入できるようにするべきです。
145+
146+ <!--
77147However when working with uninitialized memory you need to be ever-vigilant for
78148Rust trying to drop values you make like this before they're fully initialized.
79149Every control path through that variable's scope must initialize the value
80150before it ends, if it has a destructor.
81151*[This includes code panicking](unwinding.html)*.
152+ -->
153+
154+ しかし、初期化されていないメモリを扱うとき、生成した値を Rust が、以前に
155+ 完全に初期化されたものと見なしてドロップしようとしてしまわないか、常に警戒する必要があります。
156+ 値がデストラクタを持つ場合、変数のスコープを通り抜ける全てのコントロールパスは、終了時までに
157+ その値を初期化する必要があります。* [ これはコードパニックを含みます] ( unwinding.html ) *
82158
159+ <!--
83160And that's about it for working with uninitialized memory! Basically nothing
84161anywhere expects to be handed uninitialized memory, so if you're going to pass
85162it around at all, be sure to be *really* careful.
163+ -->
164+
165+ まあ、初期化されていないメモリを扱うことに関してはこんなものです。
166+ 基本的にどのような場所でも、初期化されていないメモリが渡されることは予期していません。
167+ ですからもしそのようなメモリを分配する場合、確実に* 本当に* 注意深く行なってください。
0 commit comments