From 4e4a0bb3e1bbe61b90173a90212869bec8269f27 Mon Sep 17 00:00:00 2001 From: zed Date: Thu, 16 Nov 2023 20:03:03 +0300 Subject: [PATCH] On branch main modified: src/ch06.md new file: src/ex-ch06-05.zig --- src/ch06.md | 74 +++++++++++++++++++++++++++++++++++++++++----- src/ex-ch06-05.zig | 18 +++++++++++ 2 files changed, 84 insertions(+), 8 deletions(-) create mode 100644 src/ex-ch06-05.zig diff --git a/src/ch06.md b/src/ch06.md index 2cc9d6f..8a10992 100644 --- a/src/ch06.md +++ b/src/ch06.md @@ -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 diff --git a/src/ex-ch06-05.zig b/src/ex-ch06-05.zig new file mode 100644 index 0000000..4a44740 --- /dev/null +++ b/src/ex-ch06-05.zig @@ -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}); +}