You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
If you don't work in systems programming, you probably don't spend much time thinking about the stack and the heap, so let's provide a quick overview / refresher here.
15
-
The stack represents the local variables in our program execution.
16
-
Those variables in turn can refer to or *point to* data on the heap which is a less structured area of memory available to our program.
17
-
When we need to store large amounts of data, we typically *allocate* that data on the heap.
18
-
This is useful because the heap has no memory restrictions, whereas the stack is limited.
14
+
If you don't work in systems programming, you probably don't spend much time thinking about the stack and the heap, so let's provide a quick refresher here.
15
+
The stack is a region in memory that holds local variables during our program execution.
16
+
Those variables in turn can refer to, or *point to*, data on the heap which is a less structured area of memory available to our program.
17
+
When we need to store large amounts of data or a data type whose size can change during the runtime of our program, we typically allocate that data on the heap.
18
+
The heap is more flexible and less memory-constrained than the stack.
19
19
The heap also allows data to be accessed from anywhere in the program, which is useful for data shared across different functions or modules.
20
20
However, allocating to the heap comes with a cost.
21
-
It takes more time for the program to find the space in memory to allocate the data and do some bookkeeping to return a pointer and prepare for the next allocation.
21
+
It takes more time for the program to find the space in memory to allocate data and do some bookkeeping to return a pointer and prepare for the next allocation.
22
22
When the data needs to be accessed or updated, there is additional overhead to find the the data in memory and to also reallocate memory as needed.
23
23
24
-
In Rust, if a data type is *dynamically sized*, meaning it can expand or shrink and its size is not known at compile time, it *must be* allocated on the heap.
25
-
If the data is a known, fixed-size and doesn't change, it can be allocated on the stack.
26
-
This is for more memory safety purposes.
27
-
Remember, the stack memory is limited so the compiler doesn't want there to be any surprises when the program actually runs which could lead to dangerous memory errors.
28
-
Since the pointers themselves are known and fixed in size they can be safely allocated to our program's stack.
29
-
The underlying data they point to is allocated on the heap.
24
+
Rust enforces that any type that is dynamically sized, meaning it can expand or shrink and its size is not known at compile time, must be allocated to the heap.
25
+
If the data size is known and fixed at compile time, and doesn't change during execution, it can be allocated on the stack.
26
+
This is for both memory safety and memory efficiency purposes.
27
+
Since pointers themselves are known and fixed in size they can be safely placed on our program's stack.
28
+
The underlying data they point to are allocated on the heap.
30
29
31
30
Notice in the diagram above how the vector is also a pointer type to data stored on the heap.
32
-
In Rust, the vector is actually just a *smart pointer*, unlike the slice, which is instead of a *fat pointer*.
31
+
In Rust, the vector is actually just a *smart pointer*, unlike the slice, which is instead a *fat pointer*.
33
32
A smart pointer contains additional metadata and capabilities.
34
33
It also *owns* the data instead of just borrowing a reference to it.
35
34
We'll explore the concepts of borrowing and references in more detail later on.
@@ -54,9 +53,9 @@ So let's return to the error we're getting.
54
53
55
54
In Rust, we cannot store dynamically sized data directly into a variable.
56
55
The program doesn't know until runtime how that data will grow or change and so Rust demands that we instead allocate that data on the heap instead of the stack.
57
-
Calling `[]` on a vec will return a region of dynamically-sized data, so we must always store a pointer reference to that data in a local variable.
56
+
Calling `[]` on a vector will return a region of dynamically-sized data, so we must always store a pointer reference to that data in a local variable.
58
57
We can do this by adding the `&` in front as the compiler suggested.
59
-
The `&transaction_bytes[0..4]` is now a pointer and not the actual slice data on the heap.
58
+
`&transaction_bytes[0..4]` is now a pointer and not the actual slice data on the heap.
60
59
61
60
See below for our modified program.
62
61
We've also added a `println!` in there to see what the version bytes looks like.
@@ -75,7 +74,7 @@ fn main() {
75
74
}
76
75
```
77
76
78
-
*Note: for `println!` we can insert additional characters in the brackets to modify the how the output is displayed.
77
+
*Note: for `println!` we can insert additional characters in the brackets to modify how the output is displayed.
79
78
`{:?}` will give us the debug output.
80
79
As long as the variable's type implements the `Debug` trait, we can see the debugging printout for that variable.
0 commit comments