This commit is contained in:
2026-01-19 05:43:29 +09:00
parent 40f41a4fd0
commit 0f6fddd794
36 changed files with 1724 additions and 0 deletions

View File

@@ -0,0 +1,122 @@
const std = @import("std");
const expect = std.testing.expect;
// The Zig standard library provides a pattern for allocating memory,
// which allows the programmer to choose precisely how memory allocations are done within the standard library
// - no allocations happen behind your back in the standard library.
// Zig 표준 라이브러리는 메모리 할당 패턴을 하나만 제공하며,
// 이를 통해 프로그래머는 표준 라이브러리 내부에서 메모리 할당을 어떻게 할지 선택할 수 있습니다.
// 사용자가 모르는 사이에 메모리 할당이 발생하지 않습니다.
// The most basic allocator is `std.heap.page_allocator`.
// Whenever this allocator makes an allocation, it will ask your OS for entire pages of memory;
// an allocation of a single byte will likely reserve multiple kibibytes(`KiB`).
// As asking the OS for memory requires a system call, this is also extremely inefficient for speed.
// 가장 기본적인 할당자는 `std.heap.page_allocator`입니다. 이 할당자는 메모리를 할당할 때 OS에게 전체 페이지의 메모리를 요청합니다.
// 하나의 바이트를 할당하더라도 여러 `키비바이트`(`KiB`)를 예약할 수 있습니다.
// OS에게 메모리를 요청하는 것은 시스템 호출을 필요로 하므로, 이는 매우 비효율적입니다.
// Here, we allocate 100 bytes as a []u8.
// Notice how defer is used in conjunction with a free - this is a common pattern for memory management in Zig.
// 여기서는 []u8로 100바이트를 할당합니다. defer와 free가 함께 사용되는 것을 주목하세요.
// - 이는 Zig에서 메모리 관리에 일반적인 패턴입니다.
test "allocation" {
const allocator = std.heap.page_allocator;
const memory = try allocator.alloc(u8, 100);
defer allocator.free(memory);
try expect(memory.len == 100);
try expect(@TypeOf(memory) == []u8);
}
// The `std.heap.FixedBufferAllocator` is an allocator
// that allocates memory into a fixed buffer and does not make any heap allocations.
// This is useful when heap usage is not wanted, for example, when writing a kernel.
// It may also be considered for performance reasons.
// - It will give you the error `OutOfMemory` if it has run out of bytes.
// 이 할당자는 고정된 버퍼에 메모리를 할당하며, 힙 할당을 하지 않습니다.
// 이는 힙 사용을 원하지 않을 때, 예를 들어 커널을 작성할 때 유용합니다.
// - 성능 이유로 고려될 수 있습니다. 메모리가 부족할 경우 `OutOfMemory` 오류를 발생시킵니다.
test "fixed buffer allocator" {
var buffer: [1000]u8 = undefined;
var fba = std.heap.FixedBufferAllocator.init(&buffer);
const allocator = fba.allocator();
const memory = try allocator.alloc(u8, 100);
defer allocator.free(memory);
try expect(memory.len == 100);
try expect(@TypeOf(memory) == []u8);
}
// `std.heap.ArenaAllocator` takes in a child allocator and allows you to allocate many times and only free once.
// Here, `.deinit()` is called on the arena, which frees all memory.
// Using allocator.free in this example would be a no-op (i.e. does nothing).
// `std.heap.ArenaAllocator`는 자식 할당자를 포함하고, 여러 번 할당을 할 수 있으며, 한 번에 해제할 수 있습니다.
// 여기서, `.deinit()`는 arena 할당자에서 호출하여 모든 메모리를 해제합니다.
// 이 예제에서는 `allocator.free`를 사용하면 아무 것도 하지 않습니다(`no-op`).
test "arena allocator" {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = arena.allocator();
_ = try allocator.alloc(u8, 1);
_ = try allocator.alloc(u8, 10);
_ = try allocator.alloc(u8, 100);
// allocator.free(); // no-op, no declaration `allocator.free` at zig-1.15.2`
}
// alloc and free are used for slices. For single items, consider using create and destroy.
// `alloc`과 `free`는 슬라이스에 사용됩니다. 단일 항목에 대해서는 `create`와 `destroy`를 사용하세요.
test "allocator create/destroy" {
const byte = try std.heap.page_allocator.create(u8);
defer std.heap.page_allocator.destroy(byte);
byte.* = 128;
try expect(byte.* == 128);
}
// The Zig standard library also has a general-purpose allocator.
// This is a safe allocator that can prevent double-free, use-after-free and can detect leaks.
// Safety checks and thread safety can be turned off via its configuration struct (left empty below).
// Zig's GPA is designed for safety over performance, but may still be many times faster than page_allocator.
// Zig 표준 라이브러리에는 일반적인 목적의 할당자도 있습니다.
// 이는 이중 free, free 후 사용, 메모리 누수를 방지할 수 있는 안전한 할당자입니다.
// 안전성 검사와 스레드 안전성은 구성 구조체를 통해 끌 수 있습니다 (left empty below).
// - `std.heap.GeneralPurposeAllocator(.{}){};`, `{}`는 구성 구조체입니다.
// Zig의 GPA는 성능보다 안전성을 우선시하도록 설계되었지만, `page_allocator`보다 여러 배 더 빠를 수 있습니다.
const print = std.debug.print;
test "GPA" {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
defer {
const deinit_status = gpa.deinit();
//fail test; can't try in defer as defer is executed after we return
if (deinit_status == .leak) expect(false) catch @panic("TEST FAIL");
}
const bytes = try allocator.alloc(u8, 100);
// const sample_text = "Hello, GPA!";
// for (bytes, 0..) |*byte, i| {
// byte.* = @as(u8, sample_text.ptr[i]);
// }
// bytes[sample_text.len] = @as(u8, 0);
// const bytes_slice = bytes[0 .. sample_text.len + 1 :@as(u8, 0)];
// print("bytes: {s}\n", .{bytes_slice});
defer allocator.free(bytes);
}
// For high performance (but very few safety features!), std.heap.c_allocator may be considered.
// This,however, has the disadvantage of requiring linking `Libc`, which can be done with `-lc`.
// 높은 성능(하지만 매우 적은 안전성 기능!)을 위해 `std.heap.c_allocator`를 고려할 수 있습니다.
// 그러나, `Libc`를 링크해야 하는 단점이 있으며, `-lc`로 수행할 수 있습니다.
// Benjamin Feng's talk `What's a Memory Allocator Anyway?` goes into more detail on this topic,
// and covers the implementation of allocators.
// Benjamin Feng의 토크 `What's a Memory Allocator Anyway?`는 이 주제에 대해 더 자세히 설명하고,
// 할당자의 구현을 다룹니다.