Skip to content

Commit fd03aa7

Browse files
authored
Translate unchecked-uninit.md (#42)
1 parent 7c43f2a commit fd03aa7

File tree

2 files changed

+88
-6
lines changed

2 files changed

+88
-6
lines changed

src/SUMMARY.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
* [初期化されないメモリ](uninitialized.md)
2929
* [チェックされるメモリ](checked-uninit.md)
3030
* [ドロップフラグ](drop-flags.md)
31-
* [Unchecked](unchecked-uninit.md)
31+
* [チェックされないメモリ](unchecked-uninit.md)
3232
* [所有権に基づいたリソース管理](obrm.md)
3333
* [Constructors](constructors.md)
3434
* [Destructors](destructors.md)

src/unchecked-uninit.md

Lines changed: 87 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,75 @@
1+
<!--
12
# Unchecked Uninitialized Memory
3+
-->
24

5+
# チェックされない初期化されていないメモリ
6+
7+
<!--
38
One interesting exception to this rule is working with arrays. Safe Rust doesn't
49
permit you to partially initialize an array. When you initialize an array, you
510
can either set every value to the same thing with `let x = [val; N]`, or you can
611
specify each member individually with `let x = [val1, val2, val3]`.
712
Unfortunately this is pretty rigid, especially if you need to initialize your
813
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+
これは非常に融通が利きません。
922

23+
<!--
1024
Unsafe Rust gives us a powerful tool to handle this problem:
1125
`mem::uninitialized`. This function pretends to return a value when really
1226
it does nothing at all. Using it, we can convince Rust that we have initialized
1327
a variable, allowing us to do trickier things with conditional and incremental
1428
initialization.
29+
-->
30+
31+
アンセーフな Rust では、この問題に対処するパワフルなツールが用意されています。 `mem::uninitialized` です。
32+
この関数は本当に何もせず、値を返すふりをします。これを利用することで、 Rust に
33+
変数が初期化されたと見なさせることができ、状況に応じた、インクリメンタルな初期化を
34+
行ないトリッキーなことが出来ます。
1535

36+
<!--
1637
Unfortunately, this opens us up to all kinds of problems. Assignment has a
1738
different meaning to Rust based on whether it believes that a variable is
1839
initialized or not. If it's believed uninitialized, then Rust will semantically
1940
just memcopy the bits over the uninitialized ones, and do nothing else. However
2041
if Rust believes a value to be initialized, it will try to `Drop` the old value!
2142
Since we've tricked Rust into believing that the value is initialized, we can no
2243
longer safely use normal assignment.
44+
-->
2345

46+
残念ながら、これによってあらゆる種類の問題が浮かび上がります。
47+
変数が初期化されていると Rust が思っているか、思っていないかによって、
48+
代入は異なる意味を持ちます。もし初期化していないと思っている場合、 Rust は、
49+
セマンティクス的には単にビットを初期化していないメモリにコピーし、他には
50+
何もしません。しかし、もし値が初期化していると思っている場合、 Rust は
51+
古い値を `Drop` しようとします! Rust に、値が初期化されていると信じ込ませるよう
52+
トリックをしたので、もはや安全には普通の代入は使えません。
53+
54+
<!--
2455
This is also a problem if you're working with a raw system allocator, which
2556
returns a pointer to uninitialized memory.
57+
-->
58+
59+
生のシステムアロケータを使用している場合も問題となります。このアロケータは、
60+
初期化されていないメモリへのポインタを返すからです。
2661

62+
<!--
2763
To handle this, we must use the `ptr` module. In particular, it provides
2864
three functions that allow us to assign bytes to a location in memory without
2965
dropping 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+
<!--
4092
It should go without saying that these functions, if misused, will cause serious
4193
havoc or just straight up Undefined Behavior. The only things that these
4294
functions *themselves* require is that the locations you want to read and write
4395
are allocated. However the ways writing arbitrary bits to arbitrary
4496
locations of memory can break things are basically uncountable!
97+
-->
98+
99+
言うまでもないのですが、もしこれらの関数が誤用されると、甚大な被害を引き起こしたり、
100+
未定義動作を引き起こすでしょう。これらの関数*自体*が必要とする唯一のものは、
101+
読み書きしたい場所がアロケートされているということです。しかし、
102+
任意のビットを任意のメモリの場所に書き込むことでものを壊すようなやり方は数え切れません!
45103

104+
<!--
46105
Putting this all together, we get the following:
106+
-->
107+
108+
これらを全部一緒にすると、以下のようなコードとなります。
47109

48110
```rust
49111
use std::mem;
50112
use 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] という構文を使えないことを意味しますがね!
54116
const SIZE: usize = 10;
55117

56118
let mut x: [Box<u32>; SIZE];
57119

58120
unsafe {
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

68130
println!("{:?}", x);
69131
```
70132

133+
<!--
71134
It's worth noting that you don't need to worry about `ptr::write`-style
72135
shenanigans with types which don't implement `Drop` or contain `Drop` types,
73136
because Rust knows not to try to drop them. Similarly you should be able to
74137
assign to fields of partially initialized structs directly if those fields don't
75138
contain any `Drop` types.
139+
-->
76140

141+
`Drop` を実装していない型や、 `Drop` を実装する型を含まない型との、`ptr::write` スタイルの
142+
いたずらを心配しなくてよいということは注目に値します。なぜなら Rust は、これらをドロップしようと
143+
しないと知っているからです。同じように、もし部分的に初期化されている構造体のフィールドに `Drop`
144+
実装しているものが存在しない場合、このフィールド群に直接代入できるようにするべきです。
145+
146+
<!--
77147
However when working with uninitialized memory you need to be ever-vigilant for
78148
Rust trying to drop values you make like this before they're fully initialized.
79149
Every control path through that variable's scope must initialize the value
80150
before 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+
<!--
83160
And that's about it for working with uninitialized memory! Basically nothing
84161
anywhere expects to be handed uninitialized memory, so if you're going to pass
85162
it around at all, be sure to be *really* careful.
163+
-->
164+
165+
まあ、初期化されていないメモリを扱うことに関してはこんなものです。
166+
基本的にどのような場所でも、初期化されていないメモリが渡されることは予期していません。
167+
ですからもしそのようなメモリを分配する場合、確実に*本当に*注意深く行なってください。

0 commit comments

Comments
 (0)