|
1 | 1 | ---
|
2 |
| -minutes: 5 |
| 2 | +minutes: 15 |
3 | 3 | ---
|
4 | 4 |
|
5 | 5 | # Unsafe Functions
|
6 | 6 |
|
7 |
| -## Calling Unsafe Functions |
8 |
| - |
9 | 7 | A function or method can be marked `unsafe` if it has extra preconditions you
|
10 |
| -must uphold to avoid undefined behaviour: |
11 |
| - |
12 |
| -```rust,editable |
13 |
| -extern "C" { |
14 |
| - fn abs(input: i32) -> i32; |
15 |
| -} |
16 |
| -
|
17 |
| -fn main() { |
18 |
| - let emojis = "🗻∈🌏"; |
19 |
| -
|
20 |
| - // SAFETY: The indices are in the correct order, within the bounds of the |
21 |
| - // string slice, and lie on UTF-8 sequence boundaries. |
22 |
| - unsafe { |
23 |
| - println!("emoji: {}", emojis.get_unchecked(0..4)); |
24 |
| - println!("emoji: {}", emojis.get_unchecked(4..7)); |
25 |
| - println!("emoji: {}", emojis.get_unchecked(7..11)); |
26 |
| - } |
27 |
| -
|
28 |
| - println!("char count: {}", count_chars(unsafe { emojis.get_unchecked(0..7) })); |
29 |
| -
|
30 |
| - // SAFETY: `abs` doesn't deal with pointers and doesn't have any safety |
31 |
| - // requirements. |
32 |
| - unsafe { |
33 |
| - println!("Absolute value of -3 according to C: {}", abs(-3)); |
34 |
| - } |
35 |
| -
|
36 |
| - // Not upholding the UTF-8 encoding requirement breaks memory safety! |
37 |
| - // println!("emoji: {}", unsafe { emojis.get_unchecked(0..3) }); |
38 |
| - // println!("char count: {}", count_chars(unsafe { |
39 |
| - // emojis.get_unchecked(0..3) })); |
40 |
| -} |
41 |
| -
|
42 |
| -fn count_chars(s: &str) -> usize { |
43 |
| - s.chars().count() |
44 |
| -} |
45 |
| -``` |
46 |
| - |
47 |
| -## Writing Unsafe Functions |
| 8 | +must uphold to avoid undefined behaviour. |
48 | 9 |
|
49 |
| -You can mark your own functions as `unsafe` if they require particular |
50 |
| -conditions to avoid undefined behaviour. |
| 10 | +There are two main categories: |
51 | 11 |
|
52 |
| -```rust,editable |
53 |
| -/// Swaps the values pointed to by the given pointers. |
54 |
| -/// |
55 |
| -/// # Safety |
56 |
| -/// |
57 |
| -/// The pointers must be valid and properly aligned. |
58 |
| -unsafe fn swap(a: *mut u8, b: *mut u8) { |
59 |
| - let temp = *a; |
60 |
| - *a = *b; |
61 |
| - *b = temp; |
62 |
| -} |
63 |
| -
|
64 |
| -fn main() { |
65 |
| - let mut a = 42; |
66 |
| - let mut b = 66; |
67 |
| -
|
68 |
| - // SAFETY: ... |
69 |
| - unsafe { |
70 |
| - swap(&mut a, &mut b); |
71 |
| - } |
72 |
| -
|
73 |
| - println!("a = {}, b = {}", a, b); |
74 |
| -} |
75 |
| -``` |
| 12 | +- Rust functions declared unsafe with `unsafe fn`. |
| 13 | +- Foreign functions in `extern "C"` blocks. |
76 | 14 |
|
77 | 15 | <details>
|
78 | 16 |
|
79 |
| -## Calling Unsafe Functions |
80 |
| - |
81 |
| -`get_unchecked`, like most `_unchecked` functions, is unsafe, because it can |
82 |
| -create UB if the range is incorrect. `abs` is unsafe for a different reason: it |
83 |
| -is an external function (FFI). Calling external functions is usually only a |
84 |
| -problem when those functions do things with pointers which might violate Rust's |
85 |
| -memory model, but in general any C function might have undefined behaviour under |
86 |
| -any arbitrary circumstances. |
87 |
| - |
88 |
| -The `"C"` in this example is the ABI; |
89 |
| -[other ABIs are available too](https://doc.rust-lang.org/reference/items/external-blocks.html). |
90 |
| - |
91 |
| -## Writing Unsafe Functions |
92 |
| - |
93 |
| -We wouldn't actually use pointers for a `swap` function - it can be done safely |
94 |
| -with references. |
95 |
| - |
96 |
| -Note that unsafe code is allowed within an unsafe function without an `unsafe` |
97 |
| -block. We can prohibit this with `#[deny(unsafe_op_in_unsafe_fn)]`. Try adding |
98 |
| -it and see what happens. This will likely change in a future Rust edition. |
| 17 | +We will look at the two kinds of unsafe functions next. |
99 | 18 |
|
100 | 19 | </details>
|
0 commit comments