From 1b9e3af5ce9b00cef1b2d6bb4c9765e50078e411 Mon Sep 17 00:00:00 2001 From: Akulij Date: Mon, 17 Nov 2025 19:12:22 +0700 Subject: [PATCH] vault backup: 2025-11-17 19:12:21 --- 4.2/1.md | 9 ++++----- 4.2/2.md | 14 ++++++++++++-- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/4.2/1.md b/4.2/1.md index e835a30..9118e02 100644 --- a/4.2/1.md +++ b/4.2/1.md @@ -12,8 +12,8 @@ - [x] Умеет импользовать bindgen и cc для генерации Rust API из Си header файлов - [x] Практика: сборка Си библиотеки (https://github.com/DaveGamble/cJSON). -- [ ] Прописать ОРы для глав -- [ ] Придумать квизы +- [x] Прописать ОРы для глав ✅ 2025-11-17 +- [x] Придумать квизы ✅ 2025-11-17 старт - [ ] Сначала практически расписать бест практис с с аби, @@ -72,7 +72,8 @@ unsafe extern "C" { ### Optional pointer (null optimization) - нужно ли? ### Отделение взаимодействия с ffi в отдельный крейт Если вы пишете библиотеку, взаимодействующую с C ABI, отделяйте это взаимодействие в отдельный крейт (который обычно называют \*-sys). На это есть несколько веских {{причин}}[https://doc.rust-lang.org/cargo/reference/build-scripts.html#-sys-packages]: -- Несколько разных библиотек могут переиспользовать уже написанный код для взаимодействия с библиотекой +- Несколько разных библиотек могут переиспользовать уже написанный код для взаимод +- ействия с библиотекой - Так, одна и та же библиотека не будет собираться несколько раз и не будет слинкована несколько раз (то есть не будет существовать несколько разных или одинаковых версий библиотеки в бинаре) - Легкость изменения библиотеки, от которой зависит бинарь (версии, поиска ее пути и всей остальной конфигурации) @@ -259,7 +260,6 @@ fn main() { println!("cargo:rustc-link-lib=dylib=mylib"); } ``` -// update В cargo:rustc-link-lib передано значение dylib=mylib. Оно позволяет явно указать, что нужно подгрузить динамическую библиотеку (dylib) с название mylib (у такой библиотеки будет название libmylib.so на примере linux). Значение \[тип=] опционально и может быть одним из: - dylib - динамическая библиотека - static - статическая библиотека @@ -415,7 +415,6 @@ int main() { clang main.c target/debug/libmylib.a -o ./a.exe ``` При запуске ./a.exe будет получен ожидаемый результат. -// update Для crate-type возможны следующие значения: - staticlib - сборка статической библиотеки - dylib - сборка динамической библиотеки, предназначенной для использования в rust коде. Собираться использующий код и dylib должны одной и той же версией компилятора, так как у dylib нет стабильного интерфейса diff --git a/4.2/2.md b/4.2/2.md index 03e2bf8..e5ae0cd 100644 --- a/4.2/2.md +++ b/4.2/2.md @@ -72,8 +72,13 @@ fn main() { } ``` У json обозначен не встречавшийся до этого тип `*mut _` -## Указатели -Вы уже неоднократно пользовались референсами в своем коде. В этих типах компилятор следит за временем жизни, чтобы не обратится к памяти после освобождения, а так же за валидностью памяти. Но, когда дело доходит до вызова внешней функции компилятор уже будет не способен отследить время жизни и валидность памяти. +## Сырые указатели +Вы уже неоднократно пользовались референсами в своем коде. В этих типах компилятор следит за временем жизни, чтобы не обратится к памяти после освобождения, а так же за валидностью памяти. Но, когда дело доходит до вызова внешней функции компилятор уже будет не способен отследить время жизни и валидность памяти. Поэтому в rust есть аналогичный тип - сырые указатели. Он унаследован по синтаксису и смыслу от своих предшественников (в частности от С), поэтому его описание выглядит так: +`*const T` - для неизменяемого указателя на тип T +`*mut T` - для изменяемого указателя на тип T +Внутри себя он, точно так же, как и референс, содержит адрес на память и опционально метадату, но сырой указатель не дает абсолютно никаких гарантий по памяти. Это нетипично для rust, но так необходимо при взаимодействии с внешними функциями, так для них компилятор никак не может гарантировать безопасность. +## Взаимодействие с сырым указателем +Если же сырой указатель не дает **Начать с проблемы, когда компилятор не может гарантировать безопасность по памяти (но без этого невозможно написать программу), возможно из ub** Допустим, на вход вашей функции @@ -81,13 +86,18 @@ fn main() { **Рассказать про причины ub** - как в математике есть неопределенности (к примеру, для деления на ноль), так и в языках программирования тоже есть свои неопределенности. Именно для этого и было создана такая вещь, как неопределённое поведение. +Неопределено, значит никогда не случается. Значит компилятор может оптимизировать код только соблюдая верность тех случаев, что не являются ub. (пример с nullptr дереф) **Рассказать, чем является unsafe, ответственность на программисте, про ub (НЕ является избавлением от borrow checker)** +**Как про отдельную вещь рассказать про вызов unsafe функции** + **Рассказать про применение unsafe (взаимодействие с С, оптимизация (вспомнить небезопасную либу для бэкенда: rocket или actix), написание основы/базы языка)** **Практика по пути** +**Мб рассказать про кейс с лайфтаймами** + - [ ] Определении функции unsafe если соблюдение инвариантов висит на пользователе (при написании такой функции смотреть - является ли сам интерфейс функции safe) - [ ] примеры из third party