Unsafe Functions
Calling Unsafe Functions
A function or method can be marked unsafe if it has extra preconditions you must uphold to avoid undefined behaviour:
1. ```
extern "C" {
```
2. ```
fn abs(input: i32) -> i32;
```
3. ```
}
```
5. ```
fn main() {
```
6. ```
let emojis = "🗻∈🌏";
```
8. ```
// SAFETY: The indices are in the correct order, within the bounds of the
```
9. ```
// string slice, and lie on UTF-8 sequence boundaries.
```
10. ```
unsafe {
```
11. ```
println!("emoji: {}", emojis.get_unchecked(0..4));
```
12. ```
println!("emoji: {}", emojis.get_unchecked(4..7));
```
13. ```
println!("emoji: {}", emojis.get_unchecked(7..11));
```
14. ```
}
```
16. ```
println!("char count: {}", count_chars(unsafe { emojis.get_unchecked(0..7) }));
```
18. ```
// SAFETY: `abs` doesn't deal with pointers and doesn't have any safety
```
19. ```
// requirements.
```
20. ```
unsafe {
```
21. ```
println!("Absolute value of -3 according to C: {}", abs(-3));
```
22. ```
}
```
24. ```
// Not upholding the UTF-8 encoding requirement breaks memory safety!
```
25. ```
// println!("emoji: {}", unsafe { emojis.get_unchecked(0..3) });
```
26. ```
// println!("char count: {}", count_chars(unsafe {
```
27. ```
// emojis.get_unchecked(0..3) }));
```
28. ```
}
```
30. ```
fn count_chars(s: &str) -> usize {
```
31. ```
s.chars().count()
```
32. ```
}
```
Writing Unsafe Functions
You can mark your own functions as unsafe if they require particular conditions to avoid undefined behaviour.
1. ```
/// Swaps the values pointed to by the given pointers.
```
2. ```
///
```
3. ```
/// # Safety
```
4. ```
///
```
5. ```
/// The pointers must be valid and properly aligned.
```
6. ```
unsafe fn swap(a: *mut u8, b: *mut u8) {
```
7. ```
let temp = *a;
```
8. ```
*a = *b;
```
9. ```
*b = temp;
```
10. ```
}
```
12. ```
fn main() {
```
13. ```
let mut a = 42;
```
14. ```
let mut b = 66;
```
16. ```
// SAFETY: ...
```
17. ```
unsafe {
```
18. ```
swap(&mut a, &mut b);
```
19. ```
}
```
21. ```
println!("a = {}, b = {}", a, b);
```
22. ```
}
```
This slide should take about 5 minutes.
Calling Unsafe Functions
get_unchecked, like most _unchecked functions, is unsafe, because it can create UB if the range is incorrect. abs is unsafe for a different reason: it is an external function (FFI). Calling external functions is usually only a problem when those functions do things with pointers which might violate Rust’s memory model, but in general any C function might have undefined behaviour under any arbitrary circumstances.
The "C" in this example is the ABI; other ABIs are available too.
Writing Unsafe Functions
We wouldn’t actually use pointers for a swap function - it can be done safely with references.
Note that unsafe code is allowed within an unsafe function without an unsafe block. We can prohibit this with #[deny(unsafe_op_in_unsafe_fn)]. Try adding it and see what happens. This will likely change in a future Rust edition.
