Skip to content

5.1 The Stack and the heap #219

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 25, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 43 additions & 37 deletions 1.9/ja/book/the-stack-and-the-heap.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
% スタックとヒープ
<!-- % The Stack and the Heap -->

<!--
As a systems language, Rust operates at a low level. If you’re coming from a
Expand Down Expand Up @@ -81,7 +82,7 @@ Rustはデフォルトで「スタックアロケート」、すなわち基本
Well, when a function gets called, some memory gets allocated for all of its
local variables and some other information. This is called a ‘stack frame’, and
for the purpose of this tutorial, we’re going to ignore the extra information
and just consider the local variables we’re allocating. So in this case, when
and only consider the local variables we’re allocating. So in this case, when
`main()` is run, we’ll allocate a single 32-bit integer for our stack frame.
This is automatically handled for you, as you can see; we didn’t have to write
any special Rust code or anything.
Expand Down Expand Up @@ -226,57 +227,62 @@ Let’s try a three-deep example:
3段階の深さの例を見てみましょう:

```rust
fn bar() {
fn italic() {
let i = 6;
}

fn foo() {
fn bold() {
let a = 5;
let b = 100;
let c = 1;

bar();
italic();
}

fn main() {
let x = 42;

foo();
bold();
}
```

<!--
We have some kooky function names to make the diagrams clearer.
-->
分かりやすいようにちょと変な名前をつけています。

<!--
Okay, first, we call `main()`:
-->
いいですか、まず、 `main()` を呼び出します:
それでは、まず、 `main()` を呼び出します:

| Address | Name | Value |
|---------|------|-------|
| 0 | x | 42 |

<!--
Next up, `main()` calls `foo()`:
Next up, `main()` calls `bold()`:
-->
次に、 `main()` は `foo()` を呼び出します:
次に、 `main()` は `bold()` を呼び出します:

| Address | Name | Value |
|---------|------|-------|
| 3 | c | 1 |
| 2 | b | 100 |
| 1 | a | 5 |
| **3** | **c**|**1** |
| **2** | **b**|**100**|
| **1** | **a**| **5** |
| 0 | x | 42 |

<!--
And then `foo()` calls `bar()`:
And then `bold()` calls `italic()`:
-->
そして `foo()` は `bar()` を呼び出します:
そして `bold()` は `italic()` を呼び出します:

| Address | Name | Value |
|---------|------|-------|
| 4 | i | 6 |
| 3 | c | 1 |
| 2 | b | 100 |
| 1 | a | 5 |
| *4* | *i* | *6* |
| **3** | **c**|**1** |
| **2** | **b**|**100**|
| **1** | **a**| **5** |
| 0 | x | 42 |

<!--
Expand All @@ -285,22 +291,22 @@ Whew! Our stack is growing tall.
ふう、スタックが高く伸びましたね。

<!--
After `bar()` is over, its frame is deallocated, leaving just `foo()` and
After `italic()` is over, its frame is deallocated, leaving just `bold()` and
`main()`:
-->
`bar()` が終了した後、そのフレームはデアロケートされて `foo()` と `main()` だけが残ります:
`italic()` が終了した後、そのフレームはデアロケートされて `bold()` と `main()` だけが残ります:

| Address | Name | Value |
|---------|------|-------|
| 3 | c | 1 |
| 2 | b | 100 |
| 1 | a | 5 |
| **3** | **c**|**1** |
| **2** | **b**|**100**|
| **1** | **a**| **5** |
| 0 | x | 42 |

<!--
And then `foo()` ends, leaving just `main()`:
And then `bold()` ends, leaving just `main()`:
-->
そして `foo()` が終了すると `main()` だけが残ります:
そして `bold()` が終了すると `main()` だけが残ります:

| Address | Name | Value |
|---------|------|-------|
Expand Down Expand Up @@ -392,7 +398,7 @@ location we’ve asked for.
We haven’t really talked too much about what it actually means to allocate and
deallocate memory in these contexts. Getting into very deep detail is out of
the scope of this tutorial, but what’s important to point out here is that
the heap isn’t just a stack that grows from the opposite end. We’ll have an
the heap isn’t a stack that grows from the opposite end. We’ll have an
example of this later in the book, but because the heap can be allocated and
freed in any order, it can end up with ‘holes’. Here’s a diagram of the memory
layout of a program which has been running for a while now:
Expand Down Expand Up @@ -518,7 +524,7 @@ What about when we call `foo()`, passing `y` as an argument?
| 0 | x | 5 |

<!--
Stack frames aren’t just for local bindings, they’re for arguments too. So in
Stack frames aren’t only for local bindings, they’re for arguments too. So in
this case, we need to have both `i`, our argument, and `z`, our local variable
binding. `i` is a copy of the argument, `y`. Since `y`’s value is `0`, so is
`i`’s.
Expand All @@ -530,11 +536,11 @@ binding. `i` is a copy of the argument, `y`. Since `y`’s value is `0`, so is

<!--
This is one reason why borrowing a variable doesn’t deallocate any memory: the
value of a reference is just a pointer to a memory location. If we got rid of
value of a reference is a pointer to a memory location. If we got rid of
the underlying memory, things wouldn’t work very well.
-->
これは、変数を借用してもどのメモリもデアロケートされることがないことのひとつの理由になっています。
つまり、参照の値はメモリ上の位置を示す単なるポインタです
つまり、参照の値はメモリ上の位置を示すポインタです
もしポインタが指しているメモリを取り去ってしまうと、ことが立ちゆかなくなってしまうでしょう。

# 複雑な例
Expand Down Expand Up @@ -681,11 +687,11 @@ Next, `foo()` calls `bar()` with `x` and `z`:

<!--
We end up allocating another value on the heap, and so we have to subtract one
from (2<sup>30</sup>) - 1. It’s easier to just write that than `1,073,741,822`. In any
from (2<sup>30</sup>) - 1. It’s easier to write that than `1,073,741,822`. In any
case, we set up the variables as usual.
-->
その結果、ヒープに値をもうひとつアロケートすることになるので、(2<sup>30</sup>) - 1から1を引かなくてはなりません。
そうすることは、単に `1,073,741,822` と書くよりは簡単です。
そうすることは、 `1,073,741,822` と書くよりは簡単です。
いずれにせよ、いつものように変数を準備します。

<!--
Expand Down Expand Up @@ -800,13 +806,13 @@ instead.

<!--
So if the stack is faster and easier to manage, why do we need the heap? A big
reason is that Stack-allocation alone means you only have LIFO semantics for
reason is that Stack-allocation alone means you only have 'Last In First Out (LIFO)' semantics for
reclaiming storage. Heap-allocation is strictly more general, allowing storage
to be taken from and returned to the pool in arbitrary order, but at a
complexity cost.
-->
スタックのほうが速くて管理しやすいというのであれば、なぜヒープが要るのでしょうか?
大きな理由のひとつは、スタックアロケーションだけしかないということはストレージの再利用にLIFOセマンティクスをとるしかないということだからです
大きな理由のひとつは、スタックアロケーションだけしかないということはストレージの再利用に「Last In First Out(LIFO)(訳注: 後入れ先出し)」セマンティクスをとるしかないということだからです
ヒープアロケーションは厳密により普遍的で、ストレージを任意の順番でプールから取得したり、プールに返却することが許されているのですが、よりコストがかさみます。

<!--
Expand All @@ -822,15 +828,15 @@ has two big impacts: runtime efficiency and semantic impact.
<!--## Runtime Efficiency-->

<!--
Managing the memory for the stack is trivial: The machine just
Managing the memory for the stack is trivial: The machine
increments or decrements a single value, the so-called “stack pointer”.
Managing memory for the heap is non-trivial: heap-allocated memory is freed at
arbitrary points, and each block of heap-allocated memory can be of arbitrary
size, the memory manager must generally work much harder to identify memory for
reuse.
size, so the memory manager must generally work much harder to
identify memory for reuse.
-->
スタックのメモリを管理するのは些細なことです: 機械は「スタックポインタ」と呼ばれる単一の値を増減するだけです
ヒープのメモリを管理するのは些細なことではありません: ヒープアロケートされたメモリは任意の時点で解放され、またヒープアロケートされたそれぞれのブロックは任意のサイズになりうるので、一般的にメモリマネージャは再利用するメモリを特定するためにより多く働きます
スタックのメモリを管理するのは些細なことです: 機械は「スタックポインタ」と呼ばれる単一の値を増減します
ヒープのメモリを管理するのは些細なことではありません: ヒープアロケートされたメモリは任意の時点で解放され、またヒープアロケートされたそれぞれのブロックは任意のサイズになりうるので、一般的にメモリマネージャは再利用するメモリを特定するためにより多くの仕事をします

<!--
If you’d like to dive into this topic in greater detail, [this paper][wilson]
Expand Down
155 changes: 0 additions & 155 deletions diff-1.6.0..1.9.0/src/doc/book/the-stack-and-the-heap.md

This file was deleted.