Unsafe-контекст в Rust. Указатели | OTUS

Unsafe-контекст в Rust. Указатели

Отличительная особенность Rust -- возможность его использования в низкоуровневом системном программировании. Речь идет о том, что язык позволяет обращаться к операционной системе напрямую, то есть писать драйверы и даже собственные операционные системы. Но нюанс в том, что при реализации этой возможности используется так называемый Unsafe-код, то есть "небезопасный код". А называется он так потому, что при компиляции можно избежать ряда проверок.

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

Тем не менее, Unsafe-контекст имеет право на жизнь. На практике для написания такого кода используется блок кода unsafe:

1-20219-088665.png

Не несмотря на все вышесказанное, в блоке unsafe тоже происходит ряд стандартных проверок на владение переменных, использование ссылок и пр. А ключевое слово unsafe, по сути, просто предоставляет доступ к 5 возможностям Rust и именно эти 5 возможностей не проверяются через компилятор на безопасность памяти. О каких возможностях идет речь:

  • указатели,
  • статические переменные,
  • unsafe-функции,
  • unsafe-трейты,
  • тип union.

Указатели

Позволяют выполнять обращение к значениями по конкретным адресам в памяти. Чтобы определить указатели, используется оператор разыменования * (dereference operator).

В языке программирования Rust существует 2 вида указателей:

  1. Неизменяемые либо константные. Определяются в виде *const T, где T предоставляет определенный тип.
  2. Изменяемые. Определяются в виде *mut T.

Для примера давайте создадим по одному указателю для каждого из вышеупомянутых типов:

2-20219-438d6e.png

Итак, у нас определены 2 указателя: n1 и n2. Первый из них, n1, является константным и указывает на значение типа i32. Что касается n2, то это изменяемый указатель на значение типа i32.

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

3-20219-921831.png

Ну а при создании изменяемого указателя используется изменяемая ссылка на эту переменную:

4-20219-8f2adb.png

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

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

5-20219-63d3d6.png

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

Осталось посмотреть на консольный вывод:

6-20219-712a50.png

Почему оба этих указателя имеют одинаковое значение? Потому, что оба указывают на тот же самый адрес в памяти -- на адрес переменной num.

По материалам https://metanit.com/rust/tutorial/.

Не пропустите новые полезные статьи!

Спасибо за подписку!

Мы отправили вам письмо для подтверждения вашего email.
С уважением, OTUS!

Автор
0 комментариев
Для комментирования необходимо авторизоваться
Популярное
Сегодня тут пусто