On branch main

modified:   src/ch06.md
new file:   src/ex-ch06-05.zig
This commit is contained in:
zed
2023-11-16 20:03:03 +03:00
parent 9ded5962c4
commit 4e4a0bb3e1
2 changed files with 84 additions and 8 deletions

View File

@@ -16,13 +16,13 @@
модифицированы), переменные в стеке живут, пока работает функция, который
принадлежит этот стековый кадр.
Эта глава посвящена двум темам. Первая это общий обзор нашей третьей области
памяти, кучи. А вот вторая более интересна - в языке Zig имеется вполне
ясный, но тем не менее уникальный подход к управлению динамической
памятью. Даже если Вы так или иначе умеете работать с кучей
(например, при помощи `malloc` и `free` из стандартной библиотеки языка C),
Вам всё равно следует проштудировать эту главу, поскольку в Zig
есть свои особенности.
Эта глава посвящена двум темам. Первая это общий обзор нашей третьей
области памяти, кучи. А вот вторая более интересна - в языке Zig имеется
концептуально простой, но тем не менее уникальный подход к управлению
динамической памятью. Даже если Вы так или иначе умеете работать с кучей
(например, при помощи `malloc` и `free` из стандартной библиотеки языка
C), Вам всё равно следует проштудировать эту главу, поскольку в Zig есть
свои особенности.
## Динамическая память (heap, "куча")
@@ -754,5 +754,63 @@ defer list.deinit();
И если бы где-то в `intList` создавался бы ещё один аллокатор с регионами,
то это тоже бы сработало, поскольку никто не запрещает иметь арену внутри арены.
## Распределитель с фиксированным буфером
Последний аллокатор, который мы изучим, это `std.heap.FixedBufferAllocator`,
который выделяет место под объекты в буфере (то есть в `[]u8`), который
ему предоставляется при инициализации. У этого аллокатора есть два главных преимущества.
Во-первых, поскольку память уже выделена заранее, это быстро. Во-вторых,
он естественным образом ограничивает максимальный размер выделяемой памяти,
что, с другой стороны, может считаться недостатком. Другой недостаток
состоит в том, что `free` и `destroy` у этого аллокатора работают только
с последним размещённым объектом (практически, как в стеке).
Попытка удаления не последнего объекта абсолютна безопасна, поскольку
такое удаление просто ничего не делает.
```zig
const std = @import("std");
pub fn main() !void {
var buf: [150]u8 = undefined;
var fa = std.heap.FixedBufferAllocator.init(&buf);
defer fa.reset();
const allocator = fa.allocator();
const json = try std.json.stringifyAlloc(allocator, .{
.this_is = "an anonymous struct",
.above = true,
.last_param = "are options",
}, .{.whitespace = .indent_2});
std.debug.print("{s}\n", .{json});
}
```
Этот пример напечает
```
{
"this_is": "an anonymous struct",
"above": true,
"last_param": "are options"
}
```
Уменьшите размер буфера (сделайте `[120]u8` вместо `[150]u8`) и вы получите ошибку:
```
error: OutOfMemory
...
```
Общеупотребительной является практика, когда буфер приводится в исходное
состояние (при помощи метода `reset`) и затем снова используется.
Это также относится и к `ArenaAllocator`, хотя и в меньшей степени.
## Заключение
Отсутствие в Zig аллокатора по умолчанию делает его прозрачным и гибким
в отношении управления памятью. Интерфейс `std.mem.Allocator` позволяет
строить специализиованные аллокаторы на основе более общих.
## FixedBufferAllocator

18
src/ex-ch06-05.zig Normal file
View File

@@ -0,0 +1,18 @@
const std = @import("std");
pub fn main() !void {
var buf: [150]u8 = undefined;
var fa = std.heap.FixedBufferAllocator.init(&buf);
defer fa.reset();
const allocator = fa.allocator();
const json = try std.json.stringifyAlloc(allocator, .{
.this_is = "an anonymous struct",
.above = true,
.last_param = "are options",
}, .{.whitespace = .indent_2});
std.debug.print("{s}\n", .{json});
}