1
Fork 0

Optimize out exhortations about being careful.

Yes, it is important to be careful, but repeated emphasis about it is probably
not helpful — it starts to sound like you came for a tutorial but found a
finger-wagging lecture.

Even after I removed a few of these comments, there are still several left in
the text. That's probably fine! A couple of mentions of how this is dangerous
and you ought to be careful may be a good reminder to the reader.

After making the edits, I reflowed the paragraphs that I had touched, using
emacs's "M-x fill-paragraph", with fill-column equal to 70.
This commit is contained in:
Zooko Wilcox-O'Hearn 2014-06-25 01:25:10 +00:00
parent 0550b79f73
commit e3050ffa52

View file

@ -3,13 +3,12 @@
# Introduction # Introduction
Rust aims to provide safe abstractions over the low-level details of Rust aims to provide safe abstractions over the low-level details of
the CPU and operating system, but sometimes one is forced to drop down the CPU and operating system, but sometimes one needs to drop down and
and write code at that level (those abstractions have to be created write code at that level. This guide aims to provide an overview of
somehow). This guide aims to provide an overview of the dangers and the dangers and power one gets with Rust's unsafe subset.
power one gets with Rust's unsafe subset.
Rust provides an escape hatch in the form of the `unsafe { ... }` Rust provides an escape hatch in the form of the `unsafe { ... }`
block which allows the programmer to dodge some of the compilers block which allows the programmer to dodge some of the compiler's
checks and do a wide range of operations, such as: checks and do a wide range of operations, such as:
- dereferencing [raw pointers](#raw-pointers) - dereferencing [raw pointers](#raw-pointers)
@ -18,13 +17,12 @@ checks and do a wide range of operations, such as:
- [inline assembly](#inline-assembly) - [inline assembly](#inline-assembly)
Note that an `unsafe` block does not relax the rules about lifetimes Note that an `unsafe` block does not relax the rules about lifetimes
of `&` and the freezing of borrowed data, it just allows the use of of `&` and the freezing of borrowed data.
additional techniques for skirting the compiler's watchful eye. Any
use of `unsafe` is the programmer saying "I know more than you" to the
compiler, and, as such, the programmer should be very sure that they
actually do know more about why that piece of code is valid.
In general, one should try to minimize the amount of unsafe code in a Any use of `unsafe` is the programmer saying "I know more than you" to
the compiler, and, as such, the programmer should be very sure that
they actually do know more about why that piece of code is valid. In
general, one should try to minimize the amount of unsafe code in a
code base; preferably by using the bare minimum `unsafe` blocks to code base; preferably by using the bare minimum `unsafe` blocks to
build safe interfaces. build safe interfaces.
@ -38,17 +36,17 @@ build safe interfaces.
## References ## References
One of Rust's biggest goals as a language is ensuring memory safety, One of Rust's biggest features is memory safety. This is achieved in
achieved in part via [the lifetime system](guide-lifetimes.html) which part via [the lifetime system](guide-lifetimes.html), which is how the
every `&` references has associated with it. This system is how the
compiler can guarantee that every `&` reference is always valid, and, compiler can guarantee that every `&` reference is always valid, and,
for example, never pointing to freed memory. for example, never pointing to freed memory.
These restrictions on `&` have huge advantages. However, there's no These restrictions on `&` have huge advantages. However, they also
free lunch club. For example, `&` isn't a valid replacement for C's constrain how we can use them. For example, `&` doesn't behave
pointers, and so cannot be used for FFI, in general. Additionally, identically to C's pointers, and so cannot be used for pointers in
both immutable (`&`) and mutable (`&mut`) references have some foreign function interfaces (FFI). Additionally, both immutable (`&`)
aliasing and freezing guarantees, required for memory safety. and mutable (`&mut`) references have some aliasing and freezing
guarantees, required for memory safety.
In particular, if you have an `&T` reference, then the `T` must not be In particular, if you have an `&T` reference, then the `T` must not be
modified through that reference or any other reference. There are some modified through that reference or any other reference. There are some
@ -56,7 +54,7 @@ standard library types, e.g. `Cell` and `RefCell`, that provide inner
mutability by replacing compile time guarantees with dynamic checks at mutability by replacing compile time guarantees with dynamic checks at
runtime. runtime.
An `&mut` reference has a stronger requirement: when an object has an An `&mut` reference has a different constraint: when an object has an
`&mut T` pointing into it, then that `&mut` reference must be the only `&mut T` pointing into it, then that `&mut` reference must be the only
such usable path to that object in the whole program. That is, an such usable path to that object in the whole program. That is, an
`&mut` cannot alias with any other references. `&mut` cannot alias with any other references.
@ -106,19 +104,19 @@ offered by the Rust language and libraries. For example, they
Fortunately, they come with a redeeming feature: the weaker guarantees Fortunately, they come with a redeeming feature: the weaker guarantees
mean weaker restrictions. The missing restrictions make raw pointers mean weaker restrictions. The missing restrictions make raw pointers
appropriate as a building block for (carefully!) implementing things appropriate as a building block for implementing things like smart
like smart pointers and vectors inside libraries. For example, `*` pointers and vectors inside libraries. For example, `*` pointers are
pointers are allowed to alias, allowing them to be used to write allowed to alias, allowing them to be used to write shared-ownership
shared-ownership types like reference counted and garbage collected types like reference counted and garbage collected pointers, and even
pointers, and even thread-safe shared memory types (`Rc` and the `Arc` thread-safe shared memory types (`Rc` and the `Arc` types are both
types are both implemented entirely in Rust). implemented entirely in Rust).
There are two things that you are required to be careful about There are two things that you are required to be careful about
(i.e. require an `unsafe { ... }` block) with raw pointers: (i.e. require an `unsafe { ... }` block) with raw pointers:
- dereferencing: they can have any value: so possible results include - dereferencing: they can have any value: so possible results include
a crash, a read of uninitialised memory, a use-after-free, or a crash, a read of uninitialised memory, a use-after-free, or
reading data as normal (and one hopes happens). reading data as normal.
- pointer arithmetic via the `offset` [intrinsic](#intrinsics) (or - pointer arithmetic via the `offset` [intrinsic](#intrinsics) (or
`.offset` method): this intrinsic uses so-called "in-bounds" `.offset` method): this intrinsic uses so-called "in-bounds"
arithmetic, that is, it is only defined behaviour if the result is arithmetic, that is, it is only defined behaviour if the result is
@ -177,9 +175,10 @@ code:
- store pointers privately (i.e. not in public fields of public - store pointers privately (i.e. not in public fields of public
structs), so that you can see and control all reads and writes to structs), so that you can see and control all reads and writes to
the pointer in one place. the pointer in one place.
- use `assert!()` a lot: once you've thrown away the protection of the - use `assert!()` a lot: since you can't rely on the protection of the
compiler & type-system via `unsafe { ... }` you're left with just compiler & type-system to ensure that your `unsafe` code is correct
your wits and your `assert!()`s, any bug is potentially exploitable. at compile-time, use `assert!()` to verify that it is doing the
right thing at run-time.
- implement the `Drop` for resource clean-up via a destructor, and use - implement the `Drop` for resource clean-up via a destructor, and use
RAII (Resource Acquisition Is Initialization). This reduces the need RAII (Resource Acquisition Is Initialization). This reduces the need
for any manual memory management by users, and automatically ensures for any manual memory management by users, and automatically ensures
@ -298,8 +297,8 @@ asm!(assembly template
Any use of `asm` is feature gated (requires `#![feature(asm)]` on the Any use of `asm` is feature gated (requires `#![feature(asm)]` on the
crate to allow) and of course requires an `unsafe` block. crate to allow) and of course requires an `unsafe` block.
> **Note**: the examples here are given in x86/x86-64 assembly, but all > **Note**: the examples here are given in x86/x86-64 assembly, but
> platforms are supported. > all platforms are supported.
## Assembly template ## Assembly template
@ -497,7 +496,7 @@ detects that it will overflow its stack. The example above uses the
> parts of the language may never be full specified and so details may > parts of the language may never be full specified and so details may
> differ wildly between implementations (and even versions of `rustc` > differ wildly between implementations (and even versions of `rustc`
> itself). > itself).
> >
> Furthermore, this is just an overview; the best form of > Furthermore, this is just an overview; the best form of
> documentation for specific instances of these features are their > documentation for specific instances of these features are their
> definitions and uses in `std`. > definitions and uses in `std`.
@ -584,8 +583,7 @@ fn main(_argc: int, _argv: **u8) -> int {
``` ```
Note the use of `abort`: the `exchange_malloc` lang item is assumed to Note the use of `abort`: the `exchange_malloc` lang item is assumed to
return a valid pointer, and so needs to do the check return a valid pointer, and so needs to do the check internally.
internally.
Other features provided by lang items include: Other features provided by lang items include: