[Day-21]Zig:分配器(Allocator)

Allocator 是 Zig 標準庫提供的功能,用來分配記憶體,尤其是涉及動態分配的情況。

Page

最基本的是 Page Allocator,使用 std.heap.page_allocator 取得 Allocator,再使用 .alloc(T, L) 分配記憶體空間,其中 T 是型別,L 是長度。記得要使用 defer.free() 來處理資源的釋放。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const std = @import("std");
const print = std.debug.print;

pub fn main() !void {
const allocator = std.heap.page_allocator;

const mem = try allocator.alloc(u8, 128);
defer allocator.free(mem);

print("Length: {}\n", .{mem.len});
print("Type: {}\n", .{@TypeOf(mem)});

mem[0] = 100;
mem[127] = 200;
print("{}, {}", .{ mem[0], mem[127] });
}
1
2
3
Length: 128
Type: []u8
100, 200

Fixed

如果你需要從 stack(或 static)分配記憶體,而不想從 heap,可以使用 FixedBufferAllocator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const std = @import("std");
const print = std.debug.print;

pub fn main() !void {
var stack: [128]u8 = undefined;
var fba = std.heap.FixedBufferAllocator.init(&stack);
const allocator = fba.allocator();

const mem = try allocator.alloc(u8, 64); // Note the size
defer allocator.free(mem);

print("Length: {}\n", .{mem.len});
print("Type: {}\n", .{@TypeOf(mem)});

mem[0] = 100;
mem[63] = 200;
print("{}, {}", .{ mem[0], mem[63] });
}
1
2
3
Length: 64
Type: []u8
100, 200

General Purpose

GeneralPurposeAllocator 是一個通用分配器,它是一個注重記憶體安全的分配器,會防止雙重釋放(double free)、釋放後使用(use after free),還會偵測記憶體泄漏(leak)。透過配置可以達成線程安全或關閉檢查。當一個區塊的記憶體不再使用時,會自動歸還。

大部分的情況下它應該都能勝任。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const std = @import("std");
const print = std.debug.print;

pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();

const mem = try allocator.alloc(u8, 128);
defer allocator.free(mem);

print("Length: {}\n", .{mem.len});
print("Type: {}\n", .{@TypeOf(mem)});

mem[0] = 100;
mem[127] = 200;
print("{}, {}", .{ mem[0], mem[127] });
}
1
2
3
Length: 128
Type: []u8
100, 200

Arena

ArenaAllocator 接受一個子分配器,讓你可以多次分配,但僅釋放一次。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const std = @import("std");
const print = std.debug.print;

pub fn main() !void {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit(); // Only free once
const allocator = arena.allocator();

// Allocate many times
const mem1 = try allocator.alloc(u8, 64);
const mem2 = try allocator.alloc(f32, 128);
const mem3 = try allocator.alloc(i2, 100);

print("Length: {}, {}, {}\n", .{ mem1.len, mem2.len, mem3.len });
print("Type: {}, {}, {}\n", .{ @TypeOf(mem1), @TypeOf(mem2), @TypeOf(mem3) });
}
1
2
Length: 64, 128, 100
Type: []u8, []f32, []i2

參考

本文以 Zig 0.13.0 為主。並同時發佈在:


留言可能不會立即顯示。若過了幾天仍未出現,請 Email 聯繫:)