3
3
# Introduction
4
4
5
5
Rust aims to provide safe abstractions over the low-level details of
6
- the CPU and operating system, but sometimes one needs to drop down and
7
- write code at that level. This guide aims to provide an overview of
8
- the dangers and power one gets with Rust's unsafe subset.
6
+ the CPU and operating system, but sometimes one is forced to drop down
7
+ and write code at that level (those abstractions have to be created
8
+ somehow). This guide aims to provide an overview of the dangers and
9
+ power one gets with Rust's unsafe subset.
9
10
10
11
Rust provides an escape hatch in the form of the ` unsafe { ... } `
11
- block which allows the programmer to dodge some of the compiler's
12
+ block which allows the programmer to dodge some of the compilers
12
13
checks and do a wide range of operations, such as:
13
14
14
15
- dereferencing [ raw pointers] ( #raw-pointers )
@@ -17,12 +18,13 @@ checks and do a wide range of operations, such as:
17
18
- [ inline assembly] ( #inline-assembly )
18
19
19
20
Note that an ` unsafe ` block does not relax the rules about lifetimes
20
- of ` & ` and the freezing of borrowed data.
21
+ of ` & ` and the freezing of borrowed data, it just allows the use of
22
+ additional techniques for skirting the compiler's watchful eye. Any
23
+ use of ` unsafe ` is the programmer saying "I know more than you" to the
24
+ compiler, and, as such, the programmer should be very sure that they
25
+ actually do know more about why that piece of code is valid.
21
26
22
- Any use of ` unsafe ` is the programmer saying "I know more than you" to
23
- the compiler, and, as such, the programmer should be very sure that
24
- they actually do know more about why that piece of code is valid. In
25
- general, one should try to minimize the amount of unsafe code in a
27
+ In general, one should try to minimize the amount of unsafe code in a
26
28
code base; preferably by using the bare minimum ` unsafe ` blocks to
27
29
build safe interfaces.
28
30
@@ -36,25 +38,25 @@ build safe interfaces.
36
38
37
39
## References
38
40
39
- One of Rust's biggest features is memory safety. This is achieved in
40
- part via [ the lifetime system] ( guide-lifetimes.html ) , which is how the
41
+ One of Rust's biggest goals as a language is ensuring memory safety,
42
+ achieved in part via [ the lifetime system] ( guide-lifetimes.html ) which
43
+ every ` & ` references has associated with it. This system is how the
41
44
compiler can guarantee that every ` & ` reference is always valid, and,
42
45
for example, never pointing to freed memory.
43
46
44
- These restrictions on ` & ` have huge advantages. However, they also
45
- constrain how we can use them. For example, ` & ` doesn't behave
46
- identically to C's pointers, and so cannot be used for pointers in
47
- foreign function interfaces (FFI). Additionally, both immutable (` & ` )
48
- and mutable (` &mut ` ) references have some aliasing and freezing
49
- guarantees, required for memory safety.
47
+ These restrictions on ` & ` have huge advantages. However, there's no
48
+ free lunch club. For example, ` & ` isn't a valid replacement for C's
49
+ pointers, and so cannot be used for FFI, in general. Additionally,
50
+ both immutable (` & ` ) and mutable (` &mut ` ) references have some
51
+ aliasing and freezing guarantees, required for memory safety.
50
52
51
53
In particular, if you have an ` &T ` reference, then the ` T ` must not be
52
54
modified through that reference or any other reference. There are some
53
55
standard library types, e.g. ` Cell ` and ` RefCell ` , that provide inner
54
56
mutability by replacing compile time guarantees with dynamic checks at
55
57
runtime.
56
58
57
- An ` &mut ` reference has a different constraint : when an object has an
59
+ An ` &mut ` reference has a stronger requirement : when an object has an
58
60
` &mut T ` pointing into it, then that ` &mut ` reference must be the only
59
61
such usable path to that object in the whole program. That is, an
60
62
` &mut ` cannot alias with any other references.
@@ -104,19 +106,19 @@ offered by the Rust language and libraries. For example, they
104
106
105
107
Fortunately, they come with a redeeming feature: the weaker guarantees
106
108
mean weaker restrictions. The missing restrictions make raw pointers
107
- appropriate as a building block for implementing things like smart
108
- pointers and vectors inside libraries. For example, ` * ` pointers are
109
- allowed to alias, allowing them to be used to write shared-ownership
110
- types like reference counted and garbage collected pointers, and even
111
- thread-safe shared memory types (` Rc ` and the ` Arc ` types are both
112
- implemented entirely in Rust).
109
+ appropriate as a building block for (carefully!) implementing things
110
+ like smart pointers and vectors inside libraries. For example, ` * `
111
+ pointers are allowed to alias, allowing them to be used to write
112
+ shared-ownership types like reference counted and garbage collected
113
+ pointers, and even thread-safe shared memory types (` Rc ` and the ` Arc `
114
+ types are both implemented entirely in Rust).
113
115
114
116
There are two things that you are required to be careful about
115
117
(i.e. require an ` unsafe { ... } ` block) with raw pointers:
116
118
117
119
- dereferencing: they can have any value: so possible results include
118
120
a crash, a read of uninitialised memory, a use-after-free, or
119
- reading data as normal.
121
+ reading data as normal (and one hopes happens) .
120
122
- pointer arithmetic via the ` offset ` [ intrinsic] ( #intrinsics ) (or
121
123
` .offset ` method): this intrinsic uses so-called "in-bounds"
122
124
arithmetic, that is, it is only defined behaviour if the result is
@@ -175,10 +177,9 @@ code:
175
177
- store pointers privately (i.e. not in public fields of public
176
178
structs), so that you can see and control all reads and writes to
177
179
the pointer in one place.
178
- - use ` assert!() ` a lot: since you can't rely on the protection of the
179
- compiler & type-system to ensure that your ` unsafe ` code is correct
180
- at compile-time, use ` assert!() ` to verify that it is doing the
181
- right thing at run-time.
180
+ - use ` assert!() ` a lot: once you've thrown away the protection of the
181
+ compiler & type-system via ` unsafe { ... } ` you're left with just
182
+ your wits and your ` assert!() ` s, any bug is potentially exploitable.
182
183
- implement the ` Drop ` for resource clean-up via a destructor, and use
183
184
RAII (Resource Acquisition Is Initialization). This reduces the need
184
185
for any manual memory management by users, and automatically ensures
@@ -304,8 +305,8 @@ asm!(assembly template
304
305
Any use of ` asm ` is feature gated (requires ` #![feature(asm)] ` on the
305
306
crate to allow) and of course requires an ` unsafe ` block.
306
307
307
- > ** Note** : the examples here are given in x86/x86-64 assembly, but
308
- > all platforms are supported.
308
+ > ** Note** : the examples here are given in x86/x86-64 assembly, but all
309
+ > platforms are supported.
309
310
310
311
## Assembly template
311
312
@@ -595,7 +596,7 @@ standard library itself.
595
596
> parts of the language may never be full specified and so details may
596
597
> differ wildly between implementations (and even versions of ` rustc `
597
598
> itself).
598
- >
599
+ >
599
600
> Furthermore, this is just an overview; the best form of
600
601
> documentation for specific instances of these features are their
601
602
> definitions and uses in ` std ` .
@@ -688,7 +689,8 @@ fn main(argc: int, argv: **u8) -> int {
688
689
```
689
690
690
691
Note the use of ` abort ` : the ` exchange_malloc ` lang item is assumed to
691
- return a valid pointer, and so needs to do the check internally.
692
+ return a valid pointer, and so needs to do the check
693
+ internally.
692
694
693
695
Other features provided by lang items include:
694
696
0 commit comments