diff --git a/src/MappingTable.md b/src/MappingTable.md index d1c4afa..0a49787 100644 --- a/src/MappingTable.md +++ b/src/MappingTable.md @@ -178,17 +178,18 @@ zero-cost abstractions | 無成本抽象化 | English 英文 | Traditional Chinese 正體中文 | Note 備註 ------------ |----------------------------- |---------- +address | | 暫時譯為地址 alignment | | backtrace | | bootstrap | | build | | 名詞,例:create a "build" closures | | commit | | git commit -crates | | +crates | | 有的譯本中翻譯為箱 dependencies | | destructuring let | | 用於存取 tuple fully-strict | | -hash | | +hash | | 有的譯本中翻譯為 import | | linker | | linking | | @@ -203,7 +204,7 @@ prelude | | 預先載入的函式 profiles | | regression | | repository | | -root | | +root | | 有的譯本中翻譯為根 shell | | slices | | 其他資料結構的參考 tabs | | diff --git a/src/the-stack-and-the-heap.md b/src/the-stack-and-the-heap.md index 355288e..36921eb 100644 --- a/src/the-stack-and-the-heap.md +++ b/src/the-stack-and-the-heap.md @@ -1,21 +1,17 @@ -% The Stack and the Heap +% 堆疊與堆積 -As a systems language, Rust operates at a low level. If you’re coming from a -high-level language, there are some aspects of systems programming that you may -not be familiar with. The most important one is how memory works, with a stack -and a heap. If you’re familiar with how C-like languages use stack allocation, -this chapter will be a refresher. If you’re not, you’ll learn about this more -general concept, but with a Rust-y focus. +Rust語言是一個在底層運轉的系統語言。如果您只學習過高級語言則可能不太熟悉這方面的內容。 +使用堆疊和堆積是內存工作的一個最重要的途徑。 +如果您熟知那些和C語言相似的程式語言的話這一章的內容講更新您對堆疊和堆積的認識。 +如果您還不了解這部分的內容,本章將會帶您以 Rust 語言的視角來了解它們。 -As with most things, when learning about them, we’ll use a simplified model to -start. This lets you get a handle on the basics, without getting bogged down -with details which are, for now, irrelevant. The examples we’ll use aren’t 100% -accurate, but are representative for the level we’re trying to learn at right -now. Once you have the basics down, learning more about how allocators are -implemented, virtual memory, and other advanced topics will reveal the leaks in -this particular abstraction. +和平常一樣,我們將會通過一個簡明的模型來著手學習它們。 +這是為了讓您著手基礎知識而不是糾結那些目前而言無關緊要的細節。 +這個例子並不是絕對的準確無誤。它只代表我們現在正在學習的水準。 +一旦您掌握了這些基礎之後,學習了更多有關於分配器的實作、 +虛擬記憶體、以及其他進階的主題,將會揭露出這些特定的抽象概念。 -# Memory management +# 內存管理 These two terms are about memory management. The stack and the heap are abstractions that help you determine when to allocate and deallocate memory. @@ -27,7 +23,7 @@ But the allocation is local to a function call, and is limited in size. The heap, on the other hand, is slower, and is explicitly allocated by your program. But it’s effectively unlimited in size, and is globally accessible. -# The Stack +# 堆疊 Let’s talk about this Rust program: @@ -89,7 +85,7 @@ number comes from 230, the number of bytes in a gigabyte. [^gigabyte] This memory is kind of like a giant array: addresses start at zero and go up to the final number. So here’s a diagram of our first stack frame: -| Address | Name | Value | +| 位址 | Name | Value | |---------|------|-------| | 0 | x | 42 | @@ -97,7 +93,7 @@ We’ve got `x` located at address `0`, with the value `42`. When `foo()` is called, a new stack frame is allocated: -| Address | Name | Value | +| 位址 | Name | Value | |---------|------|-------| | 2 | z | 100 | | 1 | y | 5 | @@ -116,7 +112,7 @@ value being stored. After `foo()` is over, its frame is deallocated: -| Address | Name | Value | +| 位址 | Name | Value | |---------|------|-------| | 0 | x | 42 | @@ -153,13 +149,13 @@ We have some kooky function names to make the diagrams clearer. Okay, first, we call `main()`: -| Address | Name | Value | +| 位址 | Name | Value | |---------|------|-------| | 0 | x | 42 | Next up, `main()` calls `bold()`: -| Address | Name | Value | +| 位址 | Name | Value | |---------|------|-------| | **3** | **c**|**1** | | **2** | **b**|**100**| @@ -168,7 +164,7 @@ Next up, `main()` calls `bold()`: And then `bold()` calls `italic()`: -| Address | Name | Value | +| 位址 | Name | Value | |---------|------|-------| | *4* | *i* | *6* | | **3** | **c**|**1** | @@ -180,7 +176,7 @@ Whew! Our stack is growing tall. After `italic()` is over, its frame is deallocated, leaving only `bold()` and `main()`: -| Address | Name | Value | +| 位址 | Name | Value | |---------|------|-------| | **3** | **c**|**1** | | **2** | **b**|**100**| @@ -189,14 +185,14 @@ After `italic()` is over, its frame is deallocated, leaving only `bold()` and And then `bold()` ends, leaving only `main()`: -| Address | Name | Value | +| 位址 | Name | Value | |---------|------|-------| | 0 | x | 42 | And then we’re done. Getting the hang of it? It’s like piling up dishes: you add to the top, you take away from the top. -# The Heap +# 堆積 Now, this works pretty well, but not everything can work like this. Sometimes, you need to pass some memory between different functions, or keep it alive for @@ -216,7 +212,7 @@ fn main() { Here’s what happens in memory when `main()` is called: -| Address | Name | Value | +| 位址 | Name | Value | |---------|------|--------| | 1 | y | 42 | | 0 | x | ?????? | @@ -228,7 +224,7 @@ on the heap. The actual value of the box is a structure which has a pointer to it allocates some memory for the heap, and puts `5` there. The memory now looks like this: -| Address | Name | Value | +| 位址 | Name | Value | |----------------------|------|------------------------| | (230) - 1 | | 5 | | ... | ... | ... | @@ -253,7 +249,7 @@ freed in any order, it can end up with ‘holes’. Here’s a diagram of the me layout of a program which has been running for a while now: -| Address | Name | Value | +| 位址 | Name | Value | |----------------------|------|------------------------| | (230) - 1 | | 5 | | (230) - 2 | | | @@ -282,7 +278,7 @@ implementation of `Drop` for `Box` deallocates the memory that was allocated when it was created. Great! So when `x` goes away, it first frees the memory allocated on the heap: -| Address | Name | Value | +| 位址 | Name | Value | |---------|------|--------| | 1 | y | 42 | | 0 | x | ?????? | @@ -315,7 +311,7 @@ fn main() { When we enter `main()`, memory looks like this: -| Address | Name | Value | +| 位址 | Name | Value | |---------|------|--------| | 1 | y | → 0 | | 0 | x | 5 | @@ -325,7 +321,7 @@ memory location that `x` lives at, which in this case is `0`. What about when we call `foo()`, passing `y` as an argument? -| Address | Name | Value | +| 位址 | Name | Value | |---------|------|--------| | 3 | z | 42 | | 2 | i | → 0 | @@ -377,7 +373,7 @@ fn main() { First, we call `main()`: -| Address | Name | Value | +| 位址 | Name | Value | |----------------------|------|------------------------| | (230) - 1 | | 20 | | ... | ... | ... | @@ -390,7 +386,7 @@ value pointing there. Next, at the end of `main()`, `foo()` gets called: -| Address | Name | Value | +| 位址 | Name | Value | |----------------------|------|------------------------| | (230) - 1 | | 20 | | ... | ... | ... | @@ -407,7 +403,7 @@ since `j` points at `h`. Next, `foo()` calls `baz()`, passing `z`: -| Address | Name | Value | +| 位址 | Name | Value | |----------------------|------|------------------------| | (230) - 1 | | 20 | | ... | ... | ... | @@ -423,7 +419,7 @@ Next, `foo()` calls `baz()`, passing `z`: We’ve allocated memory for `f` and `g`. `baz()` is very short, so when it’s over, we get rid of its stack frame: -| Address | Name | Value | +| 位址 | Name | Value | |----------------------|------|------------------------| | (230) - 1 | | 20 | | ... | ... | ... | @@ -436,7 +432,7 @@ over, we get rid of its stack frame: Next, `foo()` calls `bar()` with `x` and `z`: -| Address | Name | Value | +| 位址 | Name | Value | |----------------------|------|------------------------| | (230) - 1 | | 20 | | (230) - 2 | | 5 | @@ -459,7 +455,7 @@ case, we set up the variables as usual. At the end of `bar()`, it calls `baz()`: -| Address | Name | Value | +| 位址 | Name | Value | |----------------------|------|------------------------| | (230) - 1 | | 20 | | (230) - 2 | | 5 | @@ -483,7 +479,7 @@ far. After `baz()` is over, we get rid of `f` and `g`: -| Address | Name | Value | +| 位址 | Name | Value | |----------------------|------|------------------------| | (230) - 1 | | 20 | | (230) - 2 | | 5 | @@ -503,7 +499,7 @@ After `baz()` is over, we get rid of `f` and `g`: Next, we return from `bar()`. `d` in this case is a `Box`, so it also frees what it points to: (230) - 2. -| Address | Name | Value | +| 位址 | Name | Value | |----------------------|------|------------------------| | (230) - 1 | | 20 | | ... | ... | ... | @@ -516,7 +512,7 @@ what it points to: (230) - 2. And after that, `foo()` returns: -| Address | Name | Value | +| 位址 | Name | Value | |----------------------|------|------------------------| | (230) - 1 | | 20 | | ... | ... | ... |