Unsafe 函数
调用 Unsafe 函数
如果函数或方法具有额外的前提条件,您必须遵守这些前提条件来避免未定义的行为, 则可以将该函数或方法标记为 unsafe:
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. }
编写 Unsafe 函数
如果您自己编写的函数需要满足特定条件以避免未定义的行为, 您可以将这些函数标记为 unsafe。
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.
调用 Unsafe 函数
get_unchecked, like most _unchecked functions, is unsafe, because it can create UB if the range is incorrect. abs is incorrect 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.
本例中的“C”是 ABI;也可以使用其他 ABI。
编写 Unsafe 函数
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.
