Времена жизни в Rust

Поділитися
Вставка
  • Опубліковано 22 лют 2024
  • В этом видео мы поговорим о временах жизни в языке программирования Rust.
    На эту тему в интернете существует огромное количество материала, но каждый понимает её по-своему - в основном неправильно.
    Я постарался собрать и передать максимально простым способом основную суть времён жизни, или лайфтаймов в Rust. Для этого хорошо подходит визуализация:
    - синий прямоугольник обозначает время жизни структуры с момента вызова конструктора до момента её удаления в конце функции, которая ей владеет - все жёлтые и красные области лайфтаймов должны быть внутри синей области жизни самой структуры;
    - жёлтый прямоугольник обозначает время жизни немутабельной ссылки на эту структуру - от момента её взятия до последнего использования. Все немутабельные ссылки обозначаются одним цветом потому что их лайфтаймы могут пересекаться без проблем;
    - красный прямоугольник обозначает время жизни мутабельной ссылки на эту структуру - от момента её взятия до последнего использования. Все лайфтаймы мутабельных ссылок обозначаются разными оттенками красного потому что они не могут пересекаться друг с другом.
    ----------
    boosty.to/bitwiseuwu
    github.com/IoaNNUwU
    ----------
    Это видео может быть интересно любому, кто интересуется системными языками программирования, любит изучать низкоуровневые концепции и работу железа - процессора, оперативной памяти, видеокарты. Если вы знаете или хотите изучить языки C++, Go, Zig - Rust станет отличным дополнением, а возможно даже сможет сместить ваш интерес в свою сторону за счёт таких преимуществ, как безопасность памяти, потокобезопасность, современный API. Rust так же станет прекрасным языком, если вы хотите лишь немного прикоснуться к системному программированию, изучить работу железа, но при этом не оставлять высокоуровневые, простые в использовании языки, такие как Python, Java, JavaScript, Kotlin, Lua.
    На этом канале вы найдёте множество видео как на тему системного программирования, так и более общих концепций программирования, таких как ООП, системный дизайн и множество других тем, которые стоят того, чтобы их обсудить.
  • Наука та технологія

КОМЕНТАРІ • 47

  • @bitwiseuwu
    @bitwiseuwu  14 днів тому +1

    Несколько правок:
    6:40 - В C++ присутствует unique_ptr - аналог Box в Rust. Он позволяет автоматически очищать память, поэтому Box эквивалентен именно unique_ptr. Однако пример в видео скорее про то, что в С++ самый очевидный способ аллоцировать что-либо в куче является небезопасным, а сам unique_ptr требует особого обращения, когда в языке Rust структура Box подчиняется обычным правилам владения, как и все остальные структуры, поэтому автоматический менеджмент памяти происходит по умолчанию. Спасибо @user-nf8zb4qp6j и @8Johnny8Catsvill8 за замечание.

  • @kittenlord3572
    @kittenlord3572 20 днів тому +2

    Для меня очень важным выводом из этого видео стало то, что одинаковые обозначения лайфтаймов это не равенство, а что-то сродни подмножеству/меньше-равну. У нас есть лайфтайм 'a, все ссылки обозначенные 'a живут меньше или равно "слабейшему звену" лайфтайма 'a, смысл чего заключается в том, что эти ссылки зависимы от аргументов 'a. Собственно, тогда становится тривиальной логика в примере с choose_greater_number_in_each_pair - первый элемент тупла зависит от первой пары, второй элемент - от второй, обозначить их всех одним лайфтаймом было бы семантически некорректно, ибо они никак не переплетаются
    Спасибо за отличное видео!

  • @Thesinter1
    @Thesinter1 13 днів тому

    Очень годно на самом деле. Молодец!

  • @random6959
    @random6959 3 місяці тому +2

    Спасибо за видео, качественный контент. Удачи в твоих начинаниях!

  • @8Johnny8Catsvill8
    @8Johnny8Catsvill8 20 днів тому +4

    Пример с C++ полукорректный. Всё действительно так, но сравнивать сырые указатели с Box неправильно. Корректно сравнивать Box с unique_ptr и Arc с shared_ptr. Ибо не нужно забывать, что в Rust тоже есть сырые указатели.

    • @maximfukalov9106
      @maximfukalov9106 14 днів тому

      И вообще чрезмерно много пафоса против C++ ))

  • @liz2k
    @liz2k 26 днів тому +2

    Да, стало чуть-чуть понятнее, спасибо
    :)

  • @DiabloSat_off
    @DiabloSat_off 21 день тому +2

    Ура, наконец-то норм канал по расту нашел

  • @rm-rf_
    @rm-rf_ 21 день тому +1

    Видео огонь.🔥
    Хз может ли кто-то более доступно обьяснить чем ты)

  • @user-kx5ih9kw1x
    @user-kx5ih9kw1x 3 місяці тому +2

    Интересно!

  • @ainr_dev
    @ainr_dev 26 днів тому +1

    Спасибо!

  • @atommixz
    @atommixz 17 днів тому +1

    На борроучекере я поплыл

  • @user-nf8zb4qp6j
    @user-nf8zb4qp6j 25 днів тому +2

    А разве альтернативой кода с Box для cpp не будет ли демонстрация использованя unique_ptr, а не просто ручное выделение памяти?

    • @bitwiseuwu
      @bitwiseuwu  25 днів тому +2

      Я согласен, что альтернативой Box был бы unique_ptr, но пример был рассчитан на то, что в Rust автоматический менеджмент памяти - это дефолт, а в С++ самый очевидный способ аллоцировать что-либо в куче (слово new) использует ручной менеджмент, а специальные конструкции типа unique_ptr требуют особого подхода и не так удобны как обычные указатели.

  • @pavel_luck
    @pavel_luck Місяць тому +2

    Интересно, в C# с недавним введением ссылочных структур тоже появились более упрощенные правила контроля жизни ссылок

    • @bitwiseuwu
      @bitwiseuwu  Місяць тому +2

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

    • @pavel_luck
      @pavel_luck Місяць тому +1

      @@bitwiseuwu Для этого используется ключевое слово scoped, которое применяется к переменным ref struct

  • @user-mi6kq5ff8r
    @user-mi6kq5ff8r Місяць тому +1

    А чем отличается время жизни 'a (или любое другое произвольное имя) и время жизни 'static?

    • @bitwiseuwu
      @bitwiseuwu  Місяць тому +3

      'static - это короткая запись для лайфтайма, который не зависит ни от каких других параметров. Можно думать о 'static ссылке как о ссылке с бесконечным лайфтаймом. Например Box::leak возвращает ссылку которая валидна до конца работы программы, потому что данные за этой ссылкой очищаются только при завершении программы. Этот лайфтайм обозначается 'static. То же самое важное при многопоточном программировании. Если лайфтайм не зависит от других параметров, то можно безопасно использовать эту ссылку так долго, как мы этого хотим.

  • @AlexAlex-jk2tn
    @AlexAlex-jk2tn 14 днів тому +1

    Абсолютно некорректный пример из С++, я такой же могу и на расте написать. Использование new/delete в современном C++ это моветон, вы не должны их использовать, если от вас не требуется залезать в "кишки" языка, например если вы реализуете свою собственную реализацию стандартной библиотеки С++. Т.е. обычные программисты должны использовать std::array, std::unique_ptr и т.д., но нельзя использовать new. Некоторые библиотеки типа Qt могут требовать использование new, но они сами управляют памятью. В общем такой себе пример, лучше бы взяли в прмер язык C, где действительно с этим была проблема, а С++ в этом плане такой же безопасный как и Rust.

  • @miron5733
    @miron5733 27 днів тому +2

    А в чем проблема в примере на c++ создать юзера на стэке, а затем передавать в функцию по ссылке

    • @ggnet-lm7pg
      @ggnet-lm7pg 27 днів тому +1

      Сделать то можно, но если со стека удалят юзера, а кто-то обратится по ссылке, то получит segfault в лицо.

    • @tgitw-tq6iu
      @tgitw-tq6iu 25 днів тому

      @@ggnet-lm7pg Куда и кто что-то удалить со стека?

    • @AlexAlex-jk2tn
      @AlexAlex-jk2tn 14 днів тому +1

      @@ggnet-lm7pg Юзера не могут удалить, пока ваша подфункция не завершится, так что никакого segfault'а не возможно, если вы конечно не решите сохранить адрес полученный по ссылке, но вы это же можете сделать и без ссылки: вам передали переменную по значению, а вы куда-то сохранили её адрес, который станет не валидным после завершения функции. В общем следуйте стандартам: нужно сохранить адрес переменной, принимайте указатель (естесственно unique_ptr или shared_ptr), если нужно просто поработать со значением, то принимайте ссылку, если значение занимает меньше машинного слова (int, int32_t, bool и т.п.), то принимайте значение.

  • @norskiy9765
    @norskiy9765 2 місяці тому +1

    Как относишься к плюсам?

  • @GeorgyPlotnikov
    @GeorgyPlotnikov 2 місяці тому +4

    Идея для видео (или серии видео) взять паттерны из GoF и еще какие-нибудь, и сравнить их реализацию на раст и плюсах

    • @Sneg00vik
      @Sneg00vik 28 днів тому +3

      Или рассказать какие концепции из книги чистый код актуальны в Rust, а какие потеряли свою актуальность.

  • @ilyasokolov9058
    @ilyasokolov9058 25 днів тому +1

    и все же зря они не ввели возможность явного ограничения лайфтаймов. Из-за этого в некоторых редких случаях можно получить все те же use after free, доступ к не инициализированной памяти и прочие радости в safe rust.

    • @user-qt5hy3vn5p
      @user-qt5hy3vn5p 25 днів тому +1

      Ты как из палаты выбрался?

    • @ilyasokolov9058
      @ilyasokolov9058 25 днів тому

      @@user-qt5hy3vn5p а может все же ты из палаты сбежал?

    • @ilyasokolov9058
      @ilyasokolov9058 25 днів тому

      @@user-qt5hy3vn5p поищи, например, крейт cve-rs и давай ко мне в палату =))) там компилятор ломается через тип && () и функции pub const fn lifetime_translator(_val_a: &'a &'b (), val_b: &'b T) -> &'a T - все сводится к получению поведения unsafe std::mem::transmute в safe Rust. И вся проблема в немноголословности лафтаймов, из-за чего 'a и 'b становятся 'static и ссылка остаются после дропа значения

    • @tgitw-tq6iu
      @tgitw-tq6iu 24 дні тому

      @@ilyasokolov9058 Проблема не в том в чём ты узнал из видосика/статеек, а в том что без этого ансейф-хаки не работают из которых раст состоит на 98%. А ошибка там не в том что получается статик, а в дырявости системы типов вернее в её отсутствии.
      лайфтайм от лайфтайма как и любой другой генерик стирает тип и потому по определению не является корректным. Далее там противоречие происходит ошибка. Через static-хак много чего делается и он потому существует. В рамках эти преобразований ничего не проверяется. Вернее есть костыль который делает вид что он что-то проверяет, но это не так.
      Проще всего понять через тот же ансейф. Ансейф это каст чего угодно во что угодно. Да, ты можешь добавить немного проверок в рамках этого каста, но работать они будут для ограниченного случая.

  • @sibkit8183
    @sibkit8183 Місяць тому +1

    Функция не может владеть переменной. Вообще данными на которые указывает переменная вдадеет переменная, разве нет?

    • @bitwiseuwu
      @bitwiseuwu  Місяць тому +4

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

    • @konstantingavrilov7748
      @konstantingavrilov7748 24 дні тому +1

      @@bitwiseuwu Тут скорее "владение данными переходит в переменную в другом скоупе"

  • @tistaliv1491
    @tistaliv1491 Місяць тому +3

    Если в rust исползуешь Box, то используй в плюсах unique_ptr, а то сравнение очень странное

    • @bitwiseuwu
      @bitwiseuwu  Місяць тому +1

      Смысл этой демонстрации в том, что в Rust нет возможности аллоцировать величину с ручным управлением её временем жизни, тогда как new в C++ - самый простой способ аллоцировать объект в куче - делает именно это. Но я согласен, что преувеличиваю и аналог Box - это unique_ptr в C++. Тут правильнее было бы дать контрпример из языка C, в котором нет умных указателей.

    • @nanoqsh
      @nanoqsh Місяць тому +4

      @@bitwiseuwu аналог new User { 0 } в расте был бы
      ```
      use std::alloc::{alloc, Layout};
      unsafe {
      let layout = Layout::new::();
      let ptr = alloc(layout) as *mut User;
      if ptr.is_null() { panic!("alloc error"); }
      *ptr = User { id: 0 };
      }
      ```
      Но сразу понятно, что это намного более громоздко, требует unsafe-а и вообще никто так писать не будет, хотя технически это возможно.

    • @AlexAlex-jk2tn
      @AlexAlex-jk2tn 14 днів тому

      @@nanoqsh Открою тайну, за использование new в С++, тоже бьют по рукам. Так что ваш пример с unsafe как раз таки настоящий аналог пример, который автор привёл в видео, а вот unique_ptr правильный вариант. Автору действительно лучше показывать небезопасные моменты в сравнении с языком С, т.к. C++ является прямым конкурентом раста и не менее безопасен чем сам раст, поэтому в нём пофикшены подобные потенциальные проблемы с памятью.

    • @nanoqsh
      @nanoqsh 14 днів тому +2

      @@AlexAlex-jk2tn
      "не менее безопасен чем сам раст" - немного пропустил этот момент. В каком стандарте добавили борроу чеккер в плюсы? Если ни в каком, тогда данное утверждение это полнейшая ложь. Я запросто могу инвалидировать ссылку, инвалидировать итератор, удалить объект на который ссылается span или string_view и так далее. Могу запросто обратиться к элементу большему чем длина массива. Компилятор мне вообще ничего на этот счёт скажет, а просто молча скомпилирует код.
      Но больше всего мне интересно, зачем обманывать себя и других? Зачем делать вид что плюсы это прям такой же уровень safety что и раст? От чего такая тотальная неприязнь к расту, что лишь бы не писать на нём приходится сочинять подобные небылицы? Язык это просто инструмент, что мешает просто выбрать наиболее эффективный? Ну даже если кому-то и не нужна safety, то ладно, плюсы в этом случае отлично зайдут. Только вот врать зачем?

    • @AlexAlex-jk2tn
      @AlexAlex-jk2tn 13 днів тому

      @@nanoqsh Т.е. вы утверждаете, что на расте вы себе в ногу прям вообще не можите выстрелить подобным образом? В этом и проблема, что многие боготворители раста приписывают ему сверхбезопасность, но там безопасность на таком же уровне, как и в обычном C++ с использованием санитайзеров и включением соответствующих опций компилятора. Так что да, я утверждаю, что оба языка имеют одинаковый уровень безопасности, который далёк от совершенства, но в целом на любом языке можно натворить себе неприятностей, если захотеть.
      Сколько я стречал реальных проектов на расте, то обычно это одно из двух:
      1. Правильно написанный проект, который по производительности сильно отстаёт от такого же написанного на С++.
      2. Проект написанный с упором на производительность, в котором постоянно используются unsafe в итоге у него такая же производительность как у С++, но по безопасности он не лучше чем если бы его сразу на С++ написали.
      В общем если нужна производительность, то не вижу смысла писать на rust, а если не нужна, то есть куча других языков получше раста.

  • @norskiy9765
    @norskiy9765 Місяць тому

    Ну и где видео?

    • @norskiy9765
      @norskiy9765 Місяць тому +1

      Значит живой)

  • @vladsol5575
    @vladsol5575 3 місяці тому +1

    если никто не понимает значит язык ущербный, нужен язык где всем всё понятно 😂

  • @tgitw-tq6iu
    @tgitw-tq6iu 25 днів тому

    Какой же клоун. Типичная мантра на 10 минуте о том, что "одна мутбальная ссылка это про вектор и инвалидацию". Никакого отношения данный пример не имеет к теме и никак не связан с количеством ссылок.