1
+ <!--
1
2
# Unchecked Uninitialized Memory
3
+ -->
2
4
5
+ # チェックされない初期化されていないメモリ
6
+
7
+ <!--
3
8
One interesting exception to this rule is working with arrays. Safe Rust doesn't
4
9
permit you to partially initialize an array. When you initialize an array, you
5
10
can either set every value to the same thing with `let x = [val; N]`, or you can
6
11
specify each member individually with `let x = [val1, val2, val3]`.
7
12
Unfortunately this is pretty rigid, especially if you need to initialize your
8
13
array 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
+ これは非常に融通が利きません。
9
22
23
+ <!--
10
24
Unsafe Rust gives us a powerful tool to handle this problem:
11
25
`mem::uninitialized`. This function pretends to return a value when really
12
26
it does nothing at all. Using it, we can convince Rust that we have initialized
13
27
a variable, allowing us to do trickier things with conditional and incremental
14
28
initialization.
29
+ -->
30
+
31
+ アンセーフな Rust では、この問題に対処するパワフルなツールが用意されています。 ` mem::uninitialized ` です。
32
+ この関数は本当に何もせず、値を返すふりをします。これを利用することで、 Rust に
33
+ 変数が初期化されたと見なさせることができ、状況に応じた、インクリメンタルな初期化を
34
+ 行ないトリッキーなことが出来ます。
15
35
36
+ <!--
16
37
Unfortunately, this opens us up to all kinds of problems. Assignment has a
17
38
different meaning to Rust based on whether it believes that a variable is
18
39
initialized or not. If it's believed uninitialized, then Rust will semantically
19
40
just memcopy the bits over the uninitialized ones, and do nothing else. However
20
41
if Rust believes a value to be initialized, it will try to `Drop` the old value!
21
42
Since we've tricked Rust into believing that the value is initialized, we can no
22
43
longer safely use normal assignment.
44
+ -->
23
45
46
+ 残念ながら、これによってあらゆる種類の問題が浮かび上がります。
47
+ 変数が初期化されていると Rust が思っているか、思っていないかによって、
48
+ 代入は異なる意味を持ちます。もし初期化していないと思っている場合、 Rust は、
49
+ セマンティクス的には単にビットを初期化していないメモリにコピーし、他には
50
+ 何もしません。しかし、もし値が初期化していると思っている場合、 Rust は
51
+ 古い値を ` Drop ` しようとします! Rust に、値が初期化されていると信じ込ませるよう
52
+ トリックをしたので、もはや安全には普通の代入は使えません。
53
+
54
+ <!--
24
55
This is also a problem if you're working with a raw system allocator, which
25
56
returns a pointer to uninitialized memory.
57
+ -->
58
+
59
+ 生のシステムアロケータを使用している場合も問題となります。このアロケータは、
60
+ 初期化されていないメモリへのポインタを返すからです。
26
61
62
+ <!--
27
63
To handle this, we must use the `ptr` module. In particular, it provides
28
64
three functions that allow us to assign bytes to a location in memory without
29
65
dropping the old value: `write`, `copy`, and `copy_nonoverlapping`.
66
+ -->
67
+
68
+ これに対処するには、 ` ptr ` モジュールを使用しなければなりません。
69
+ 特にこのモジュールは、古い値をドロップせずに、メモリ上の場所に値を代入することが
70
+ 可能となる 3 つの関数を提供しています: ` write ` 、` copy ` 、` copy_nonoverlapping ` です。
30
71
72
+ <!--
31
73
* `ptr::write(ptr, val)` takes a `val` and moves it into the address pointed
32
74
to by `ptr`.
33
75
* `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`.
36
78
* `ptr::copy_nonoverlapping(src, dest, count)` does what `copy` does, but a
37
79
little faster on the assumption that the two ranges of memory don't overlap.
38
80
(this is equivalent to memcpy -- note that the argument order is reversed!)
81
+ -->
39
82
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
+ <!--
40
92
It should go without saying that these functions, if misused, will cause serious
41
93
havoc or just straight up Undefined Behavior. The only things that these
42
94
functions *themselves* require is that the locations you want to read and write
43
95
are allocated. However the ways writing arbitrary bits to arbitrary
44
96
locations of memory can break things are basically uncountable!
97
+ -->
98
+
99
+ 言うまでもないのですが、もしこれらの関数が誤用されると、甚大な被害を引き起こしたり、
100
+ 未定義動作を引き起こすでしょう。これらの関数* 自体* が必要とする唯一のものは、
101
+ 読み書きしたい場所がアロケートされているということです。しかし、
102
+ 任意のビットを任意のメモリの場所に書き込むことでものを壊すようなやり方は数え切れません!
45
103
104
+ <!--
46
105
Putting this all together, we get the following:
106
+ -->
107
+
108
+ これらを全部一緒にすると、以下のようなコードとなります。
47
109
48
110
``` rust
49
111
use std :: mem;
50
112
use std :: ptr;
51
113
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] という構文を使えないことを意味しますがね !
54
116
const SIZE : usize = 10 ;
55
117
56
118
let mut x : [Box <u32 >; SIZE ];
57
119
58
120
unsafe {
59
- // convince Rust that x is Totally Initialized
121
+ // Rust に x が完全に初期化されたと思わせます
60
122
x = mem :: uninitialized ();
61
123
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 はパニックできません
64
126
ptr :: write (& mut x [i ], Box :: new (i as u32 ));
65
127
}
66
128
}
67
129
68
130
println! (" {:?}" , x );
69
131
```
70
132
133
+ <!--
71
134
It's worth noting that you don't need to worry about `ptr::write`-style
72
135
shenanigans with types which don't implement `Drop` or contain `Drop` types,
73
136
because Rust knows not to try to drop them. Similarly you should be able to
74
137
assign to fields of partially initialized structs directly if those fields don't
75
138
contain any `Drop` types.
139
+ -->
76
140
141
+ ` Drop ` を実装していない型や、 ` Drop ` を実装する型を含まない型との、` ptr::write ` スタイルの
142
+ いたずらを心配しなくてよいということは注目に値します。なぜなら Rust は、これらをドロップしようと
143
+ しないと知っているからです。同じように、もし部分的に初期化されている構造体のフィールドに ` Drop ` を
144
+ 実装しているものが存在しない場合、このフィールド群に直接代入できるようにするべきです。
145
+
146
+ <!--
77
147
However when working with uninitialized memory you need to be ever-vigilant for
78
148
Rust trying to drop values you make like this before they're fully initialized.
79
149
Every control path through that variable's scope must initialize the value
80
150
before it ends, if it has a destructor.
81
151
*[This includes code panicking](unwinding.html)*.
152
+ -->
153
+
154
+ しかし、初期化されていないメモリを扱うとき、生成した値を Rust が、以前に
155
+ 完全に初期化されたものと見なしてドロップしようとしてしまわないか、常に警戒する必要があります。
156
+ 値がデストラクタを持つ場合、変数のスコープを通り抜ける全てのコントロールパスは、終了時までに
157
+ その値を初期化する必要があります。* [ これはコードパニックを含みます] ( unwinding.html ) *
82
158
159
+ <!--
83
160
And that's about it for working with uninitialized memory! Basically nothing
84
161
anywhere expects to be handed uninitialized memory, so if you're going to pass
85
162
it around at all, be sure to be *really* careful.
163
+ -->
164
+
165
+ まあ、初期化されていないメモリを扱うことに関してはこんなものです。
166
+ 基本的にどのような場所でも、初期化されていないメモリが渡されることは予期していません。
167
+ ですからもしそのようなメモリを分配する場合、確実に* 本当に* 注意深く行なってください。
0 commit comments