Wording tweaks

This commit is contained in:
Bradlee Speice 2019-02-04 00:12:01 -05:00
parent ac1d473ac2
commit f7a5fea93d
No known key found for this signature in database
GPG Key ID: 48BEA6257238E620
4 changed files with 21 additions and 17 deletions

View File

@ -75,16 +75,20 @@ we'll follow this guide:
- Boxed closures (FnBox, others?) are heap allocated - Boxed closures (FnBox, others?) are heap allocated
- "Move" semantics don't trigger new allocation; just a change of ownership, - "Move" semantics don't trigger new allocation; just a change of ownership,
so are incredibly fast so are incredibly fast
- In examples, is address of data before and after the same?
- Can `Copy` trigger allocation?
- Stack-based alternatives to standard library types should be preferred (spin, parking_lot) - Stack-based alternatives to standard library types should be preferred (spin, parking_lot)
## Smart pointers # Smart pointers
The first thing to note are the "smart pointer" types. The first thing to note are the "smart pointer" types.
When you have data that must outlive the scope in which it is declared, When you have data that must outlive the scope in which it is declared,
or your data is of unknown or dynamic size, you'll make use of these types. or your data is of unknown or dynamic size, you'll make use of these types.
The term [smart pointer](https://en.wikipedia.org/wiki/Smart_pointer) The term [smart pointer](https://en.wikipedia.org/wiki/Smart_pointer)
comes from C++, and is used to describe objects that are responsible for managing comes from C++, and while it's closely linked to a general design pattern of
["Resource Acquisition Is Initialization"](https://en.cppreference.com/w/cpp/language/raii),
we'll use it here specifically to describe objects that are responsible for managing
ownership of data allocated on the heap. The smart pointers available in the `alloc` ownership of data allocated on the heap. The smart pointers available in the `alloc`
crate should look mostly familiar: crate should look mostly familiar:
- [`Box`](https://doc.rust-lang.org/alloc/boxed/struct.Box.html) - [`Box`](https://doc.rust-lang.org/alloc/boxed/struct.Box.html)
@ -97,10 +101,10 @@ though more than can be covered in this article. Some examples:
- [`RwLock`](https://doc.rust-lang.org/std/sync/struct.RwLock.html) - [`RwLock`](https://doc.rust-lang.org/std/sync/struct.RwLock.html)
- [`Mutex`](https://doc.rust-lang.org/std/sync/struct.Mutex.html) - [`Mutex`](https://doc.rust-lang.org/std/sync/struct.Mutex.html)
Finally, there is one [gotcha](https://www.merriam-webster.com/dictionary/gotcha): Finally, there is one ["gotcha"](https://www.merriam-webster.com/dictionary/gotcha):
cell types (like [`RefCell`](https://doc.rust-lang.org/stable/core/cell/struct.RefCell.html)) cell types (like [`RefCell`](https://doc.rust-lang.org/stable/core/cell/struct.RefCell.html))
look and behave like smart pointers, but don't actually require heap allocation. follow the RAII pattern, but don't involve heap allocation. Check out the
Check out the [`core::cell` docs](https://doc.rust-lang.org/stable/core/cell/index.html) [`core::cell` docs](https://doc.rust-lang.org/stable/core/cell/index.html)
for more information. for more information.
When a smart pointer is created, the data it is given is placed in heap memory and When a smart pointer is created, the data it is given is placed in heap memory and
@ -138,7 +142,7 @@ pub fn my_cow() {
``` ```
-- [Compiler Explorer](https://godbolt.org/z/SaDpWg) -- [Compiler Explorer](https://godbolt.org/z/SaDpWg)
## Collections # Collections
Collections types use heap memory because they have dynamic size; they will request more memory Collections types use heap memory because they have dynamic size; they will request more memory
[when needed](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.reserve), [when needed](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.reserve),

View File

@ -99,7 +99,7 @@ With all that in mind, let's talk about situations in which we're guaranteed to
- Closures capture their arguments on the stack - Closures capture their arguments on the stack
- Generics will use stack allocation, even with dynamic dispatch. - Generics will use stack allocation, even with dynamic dispatch.
## Structs # Structs
The simplest case comes first. When creating vanilla `struct` objects, we use stack memory The simplest case comes first. When creating vanilla `struct` objects, we use stack memory
to hold their contents: to hold their contents:
@ -132,7 +132,7 @@ pub fn make_line() {
Note that while some extra-fancy instructions are used for memory manipulation in the assembly, Note that while some extra-fancy instructions are used for memory manipulation in the assembly,
the `sub rsp, 64` instruction indicates we're still working with the stack. the `sub rsp, 64` instruction indicates we're still working with the stack.
## Function arguments # Function arguments
Have you ever wondered how functions communicate with each other? Like, once the variables are Have you ever wondered how functions communicate with each other? Like, once the variables are
given to you, everything's fine. But how do you "give" those variables to another function? given to you, everything's fine. But how do you "give" those variables to another function?
@ -237,7 +237,7 @@ and passing by reference (either moving ownership or passing a pointer) may have
[slightly different layouts in assembly](https://godbolt.org/z/sKi_kl), but will [slightly different layouts in assembly](https://godbolt.org/z/sKi_kl), but will
still use either stack memory or CPU registers. still use either stack memory or CPU registers.
## Enums # Enums
If you've ever worried that wrapping your types in If you've ever worried that wrapping your types in
[`Option`](https://doc.rust-lang.org/stable/core/option/enum.Option.html) or [`Option`](https://doc.rust-lang.org/stable/core/option/enum.Option.html) or
@ -275,7 +275,7 @@ in assembly, so I'll instead point you to the
[`core::mem::size_of`](https://doc.rust-lang.org/stable/core/mem/fn.size_of.html#size-of-enums) [`core::mem::size_of`](https://doc.rust-lang.org/stable/core/mem/fn.size_of.html#size-of-enums)
documentation. documentation.
## Arrays # Arrays
The array type is guaranteed to be stack allocated, which is why the array size must The array type is guaranteed to be stack allocated, which is why the array size must
be declared. Interestingly enough, this can be used to cause safe Rust programs to crash: be declared. Interestingly enough, this can be used to cause safe Rust programs to crash:
@ -320,7 +320,7 @@ There aren't any security implications of this (no memory corruption occurs),
but it's good to note that the Rust compiler won't move arrays into heap memory but it's good to note that the Rust compiler won't move arrays into heap memory
even if they can be reasonably expected to overflow the stack. even if they can be reasonably expected to overflow the stack.
## Closures # Closures
Rules for how anonymous functions capture their arguments are typically language-specific. Rules for how anonymous functions capture their arguments are typically language-specific.
In Java, [Lambda Expressions](https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html) In Java, [Lambda Expressions](https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html)
@ -387,7 +387,7 @@ pub fn complex() {
In every circumstance though, the compiler ensured that no heap allocations were necessary. In every circumstance though, the compiler ensured that no heap allocations were necessary.
## Generics # Generics
Traits in Rust come in two broad forms: static dispatch (monomorphization, `impl Trait`) Traits in Rust come in two broad forms: static dispatch (monomorphization, `impl Trait`)
and dynamic dispatch (trait objects, `dyn Trait`). While dynamic dispatch is often and dynamic dispatch (trait objects, `dyn Trait`). While dynamic dispatch is often
@ -444,5 +444,5 @@ pub fn do_call() {
``` ```
-- [Compiler Explorer](https://godbolt.org/z/u_yguS) -- [Compiler Explorer](https://godbolt.org/z/u_yguS)
It's hard to imagine practical situations where dynamic dispatch It's hard to imagine practical situations where dynamic dispatch would be
would be used for objects that aren't heap allocated, but it can be done. used for objects that aren't heap allocated, but it technically can be done.

View File

@ -16,7 +16,7 @@ we'll go into below. The
[full specification](https://github.com/rust-lang/rfcs/blob/master/text/0246-const-vs-static.md) [full specification](https://github.com/rust-lang/rfcs/blob/master/text/0246-const-vs-static.md)
for these two memory types is available, but we'll take a hands-on approach to the topic. for these two memory types is available, but we'll take a hands-on approach to the topic.
## **const** # **const**
The quick summary is this: `const` declares a read-only block of memory that is loaded The quick summary is this: `const` declares a read-only block of memory that is loaded
as part of your program binary (during the call to [exec(3)](https://linux.die.net/man/3/exec)). as part of your program binary (during the call to [exec(3)](https://linux.die.net/man/3/exec)).
@ -144,7 +144,7 @@ but the specifications are clear enough: *don't rely on pointers to `const`
values being consistent*. To be frank, caring about locations for `const` values values being consistent*. To be frank, caring about locations for `const` values
is almost certainly a code smell. is almost certainly a code smell.
## **static** # **static**
Static variables are related to `const` variables, but take a slightly different approach. Static variables are related to `const` variables, but take a slightly different approach.
When the compiler can guarantee that a *reference* is fixed for the life of a program, When the compiler can guarantee that a *reference* is fixed for the life of a program,