Сравнение с ручной памятью C и Rust
В прокате инструментов важно не только получить дрель. Нужно знать, кто её возвращает, когда и что делать с выданной другому человеку запиской «можешь взять». Если записка пережила возврат дрели, она больше не даёт права пользоваться вещью. С памятью та же проблема: адрес можно скопировать, а срок жизни ресурса от этого не продлевается.
Сравним подходы языков только вокруг этого одного вопроса. Знание C или Rust для урока не требуется: сначала сформулируем договор обычными словами.
Одна мысль урока
В Zig владелец и срок жизни определяются явным договором, а не автоматически проверяются целиком.
Опора из прошлого урока: Виды аллокаторов из стандартной библиотеки.
От картинки к записи
Есть три роли: источник памяти выдаёт блок, владелец отвечает за его освобождение, читатель временно пользуется данными. Один человек может выполнять все роли, но в функции они часто разделяются. Название типа среза не сообщает автоматически, какая именно роль принадлежит вызывающему.
Заимствованный доступ
в этом уроке обычное описание договора, а не отдельная проверка Zig. Функция countNonZero читает
чужой срез и возвращает число. Она не должна вызывать free и не возвращает окно, которое заставило
бы отслеживать жизнь входа после вызова.
Функция duplicate, напротив, создаёт новый блок и передаёт его вызывающему. Это принадлежащий результат. Одинаковая запись []u8 сама по себе не различает оба случая. Поэтому имена, комментарии и место выделения нужны читателю. В библиотечном API полезно прямо написать, каким источником освобождать результат.
В C часто работают с парой malloc и free. Первая выдаёт блок, вторая возвращает. Автор обязан сохранить длину, учесть неуспех и не использовать блок после free. Указатель сам по себе не запрещает преждевременное или повторное освобождение. Эта ответственность близка Zig, но в Zig интерфейс аллокатора передаётся явно, а срез может хранить длину рядом с адресом.
В Rust значительная часть правил владельца и доступа проверяется статически, то есть до запуска. Язык может отвергнуть программу, если из записи следует недопустимое совместное использование или слишком короткая жизнь данных. Сегодня не изучаем механизм этой проверки и не используем специальные термины из его системы. Достаточно разницы: Zig не обещает такую полную статическую проверку сроков жизни.
Это не соревнование «кто безопаснее вообще». У разных задач разные ограничения: доступность библиотек, опыт команды, взаимодействие с готовым C-кодом, допустимость автоматических ограничений. Проверки Zig в Debug и ReleaseSafe полезны, но не заменяют договор владельца. Контролируемая отладка помогает обнаружить конкретную ошибку, а не математически доказать её отсутствие во всех входах.
Можно сделать хороший договор без сложного типа: вход только читается, не сохраняется после возврата, результат число. Можно сделать плохой: функция возвращает окно на локальный массив, а комментарий говорит «всё безопасно». Комментарий не продлевает память. Поэтому разбор срока жизни всегда опирается на настоящие места создания и уничтожения.
Выбирай самый простой доступ, достаточный для задачи. Для подсчёта не нужна копия. Для хранения текста после перезаписи входного буфера может понадобиться отдельный блок. Для обработки группы данных с общим завершением пригодится арена. Это решения о жизни объектов, а не о любимом названии аллокатора.
премиум-урок
Продолжение в премиуме: 1 200 ₽ в месяц или 10 000 ₽ в год. Вместе с ним серверные проверки задач и школьные токены AI-коуча.
Оплата пока не подключена: премиум и курсы открываются промокодом.