On branch main

modified:   src/ch05.md
This commit is contained in:
zed
2023-11-21 11:43:00 +03:00
parent a0e49c48e2
commit d659cd4c5a

View File

@@ -10,7 +10,7 @@
(например, прочитать файл), может запросто использовать несколько сотен
мегабайт памяти, сделать что-то потрясающее и далее выйти. По выходу
операционная система освобождает все ресурсы (память, в частности),
которые были исопльзованы программой, пока она выполнялась. Освобожденная
которые были использованы программой, пока она выполнялась. Освобожденная
память затем может быть отдана в пользование другим программам.
Однако, для программ, которые работают днями, месяцами и даже годами,
@@ -18,7 +18,7 @@
далеко не только какой-то отдельно взятой программе, но и другим,
исполняющимся на этой же машине. То есть попросту невозможно ждать, пока
какая-то программа не завершится и память станет доступной. Многие языки
программиования имеют среду времени выполнения, в которую входит сборщик
программирования имеют среду времени выполнения, в которую входит сборщик
мусора - его первейшая задача как раз и есть отслеживание более не нужной
памяти и её освобождение. Как уже пару раз упоминалось в предыдущих
главах, в Zig нет сборщика мусора, поэтому его роль выполняет разработчик
@@ -28,7 +28,7 @@
область, где хранятся данные, не подлежащие модификации, то есть
константы, включая строковые. Эти данные содержатся в исполнимом файле.
Такие данные существуют (то есть занимают память) всё время выполнения
программы, причём объём занимаемой имм памяти остаётся постоянным, он не
программы, причём объём занимаемой ими памяти остаётся постоянным, он не
может ни увеличиться, ни уменьшится. Но это не то, о чём нас следует
беспокоиться, разве что общее количество таких данных сказывается на
размере исполнимого файла.
@@ -47,9 +47,9 @@
переменная доступна только в той области видимости, где она была
объявлена. В Zig области видимости это, по сути, блоки кода, окружённые
фигурными скобками (`{ ... }`). Большинство переменных привязаны или к
функции (включая её аргументы), или к управляющим констркуциям, таким
функции (включая её аргументы), или к управляющим конструкциям, таким
как, например, `if`. Однако, как мы видели, можно создавать любые блоки и
тем самым, проивольные области видимости.
тем самым, произвольные области видимости.
В предыдущей главе мы визуализировали содержимое памяти для функций
`main` и `levelUp`, используя экземпляры переменной типа `User`:
@@ -136,7 +136,7 @@ main: user -> ------------- (id: 1043368d0)
В обычных программах стек довольно сильно заполнен, поскольку типичная
программа использует множество библиотек, и как следствие глубина
вложенности вызовов функций может быть достаточно большой. Обычно это не
является проблемой, но иногда можно довести дело до переполения стека.
является проблемой, но иногда можно довести дело до переполнения стека.
Зачастую это случается с рекурсивными функциями, то есть функциями,
вызывающими саму себя.
@@ -149,14 +149,14 @@ main: user -> ------------- (id: 1043368d0)
Выделение памяти на стеке и её освобождение это очень быстрые операции,
поскольку это всего лишь декремент/инкремент указателя вершины стека
(обычно стек "растёт" в сторону меньшмх адресов памяти).
(обычно стек "растёт" в сторону меньших адресов памяти).
## "Висячие" указатели (dangling pointers)
Стек вызовов это замечательный механизм в силу его простоты и эффективности.
Однако нас должно насторожить следующее обстоятельство: когда функция
завершает работу, всё её локальные переменные как бы исчезают.
Это, по идее, разумно, в конце концов, это же лоакльные переменные,
Это, по идее, разумно, в конце концов, это же локальные переменные,
они нужны только самой функции, но есть одно но. Рассмотрим следующий пример:
```zig
@@ -217,7 +217,7 @@ User 16777216 has power of -1
Почему так происходит? Дело в том, что функция `User.init` возвращает
**адрес локальной переменной**, то есть `&user`. Это называется "висячий"
указатель, источник многих проблем, вплоть до аварийного завершения или,
по крайней мере, как мы только что виделм, явно некорректное поведения программы.
по крайней мере, как мы только что видели, явно некорректное поведения программы.
Когда стековый кадр "уничтожается", всякие ссылки в ту область памяти,
которую этот кадр занимал, становятся попросту бессмысленными. И что мы