Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Ключевое слово unsafe

Ключевое слово unsafe используется для создания или снятия обязательства доказывать безопасность чего-либо. Конкретно:

  • Оно используется для пометки кода, который определяет дополнительные условия безопасности, которые должны соблюдаться в других местах.
    • Это включает unsafe fn, unsafe static и unsafe trait.
  • Оно используется для пометки кода, для которого программист утверждает, что удовлетворяет условиям безопасности, определенным в других местах.
    • Это включает unsafe {}, unsafe impl, unsafe fn без unsafe_op_in_unsafe_fn, unsafe extern и #[unsafe(attr)].

Далее обсуждается каждый из этих случаев. См. документацию по ключевым словам для некоторых иллюстративных примеров.

Ключевое слово unsafe может встречаться в нескольких различных контекстах:

  • небезопасные функции (unsafe fn)
  • небезопасные блоки (unsafe {})
  • небезопасные трейты (unsafe trait)
  • небезопасные реализации трейтов (unsafe impl)
  • небезопасные внешние блоки (unsafe extern)
  • небезопасные внешние статические переменные (unsafe static)
  • небезопасные атрибуты (#[unsafe(attr)])

Небезопасные функции (unsafe fn)

Небезопасные функции - это функции, которые не являются безопасными во всех контекстах и/или для всех возможных входных данных. Мы говорим, что они имеют дополнительные условия безопасности, которые являются требованиями, которые должны соблюдаться всеми вызывающими сторонами и которые компилятор не проверяет. Например, get_unchecked имеет дополнительное условие безопасности, что индекс должен быть в пределах. Небезопасная функция должна сопровождаться документацией, объясняющей, что это за дополнительные условия безопасности.

Такая функция должна быть предварена ключевым словом unsafe и может быть вызвана только изнутри блока unsafe или изнутри unsafe fn без линты unsafe_op_in_unsafe_fn.

Небезопасные блоки (unsafe {})

Блок кода может быть предварен ключевым словом unsafe, чтобы разрешить использование небезопасных действий, как определено в главе Небезопасность, таких как вызов других небезопасных функций или разыменование сырых указателей.

По умолчанию тело небезопасной функции также считается небезопасным блоком; это можно изменить, включив линту unsafe_op_in_unsafe_fn.

Помещая операции в небезопасный блок, программист заявляет, что он позаботился об удовлетворении дополнительных условий безопасности всех операций внутри этого блока.

Небезопасные блоки являются логическим двойником небезопасных функций: где небезопасные функции определяют обязательство доказательства, которое должны выполнять вызывающие стороны, небезопасные блоки утверждают, что все соответствующие обязательства доказательства функций или операций, вызванных внутри блока, были выполнены. Существует много способов выполнить обязательства доказательства; например, могут быть проверки во время выполнения или инварианты структур данных, которые гарантируют, что определенные свойства точно истинны, или небезопасный блок может быть внутри unsafe fn, в котором случае блок может использовать обязательства доказательства этой функции для выполнения обязательств доказательства, возникающих внутри блока.

Небезопасные блоки используются для обертывания внешних библиотек, прямого использования оборудования или реализации функций, отсутствующих непосредственно в языке. Например, Rust предоставляет языковые возможности, необходимые для реализации безопасного параллелизма памяти на языке, но реализация потоков и передачи сообщений в стандартной библиотеке использует небезопасные блоки.

Система типов Rust является консервативным приближением динамических требований безопасности, поэтому в некоторых случаях использование безопасного кода имеет производительностные затраты. Например, двусвязный список не является древовидной структурой и может быть представлен только указателями с подсчетом ссылок в безопасном коде. Используя unsafe блоки для представления обратных ссылок как сырых указателей, его можно реализовать без подсчета ссылок. (См. “Learn Rust With Entirely Too Many Linked Lists” для более глубокого изучения этого конкретного примера.)

Небезопасные трейты (unsafe trait)

Небезопасный трейт - это трейт, который поставляется с дополнительными условиями безопасности, которые должны соблюдаться реализациями трейта. Небезопасный трейт должен сопровождаться документацией, объясняющей, что это за дополнительные условия безопасности.

Такой трейт должен быть предварен ключевым словом unsafe и может быть реализован только блоками unsafe impl.

Небезопасные реализации трейтов (unsafe impl)

При реализации небезопасного трейта реализация должна быть предварена ключевым словом unsafe. Написав unsafe impl, программист заявляет, что он позаботился об удовлетворении дополнительных условий безопасности, требуемых трейтом.

Небезопасные реализации трейтов являются логическим двойником небезопасных трейтов: где небезопасные трейты определяют обязательство доказательства, которое должны выполнять реализации, небезопасные реализации утверждают, что все соответствующие обязательства доказательства были выполнены.

Небезопасные внешние блоки (unsafe extern)

Программист, который объявляет внешний блок, должен гарантировать, что сигнатуры содержащихся в нем элементов корректны. Невыполнение этого может привести к неопределенному поведению. То, что это обязательство было выполнено, указывается написанием unsafe extern.

2024 Edition differences

До редакции 2024 года блоки extern разрешалось использовать без квалификации как unsafe.

Небезопасные атрибуты (#[unsafe(attr)])

Небезопасный атрибут - это атрибут, который имеет дополнительные условия безопасности, которые должны соблюдаться при использовании атрибута. Компилятор не может проверить, были ли эти условия соблюдены. Чтобы утверждать, что они были соблюдены, эти атрибуты должны быть обернуты в unsafe(..), например #[unsafe(no_mangle)].