Skip to content

Exercises

The exercises in this section are meant to make allocation habits precise. Each one should be written as a complete program unless stated otherwise.

The exercises in this section are meant to make allocation habits precise. Each one should be written as a complete program unless stated otherwise.

Exercise 12-25. Allocate a slice of 16 u8 values with std.heap.page_allocator. Fill it with zeroes. Print its length. Free it before the program exits.

Exercise 12-26. Allocate a slice of 8 i32 values. Store the values 0 through 7 in it. Print the slice with {any}.

Exercise 12-27. Write a function:

fn allocBytes(allocator: std.mem.Allocator, len: usize) ![]u8

The function should allocate len bytes, set them all to zero, and return the slice. The caller must free the returned memory.

Exercise 12-28. Write a function:

fn allocCopy(allocator: std.mem.Allocator, source: []const u8) ![]u8

The function should allocate a new byte slice and copy source into it. The caller must own the copy.

Exercise 12-29. Create a std.heap.GeneralPurposeAllocator in main. Pass its allocator to a function named run. Do all heap allocation inside run.

Exercise 12-30. Write a program that allocates one Point value with allocator.create.

const Point = struct {
    x: i32,
    y: i32,
};

Set both fields, print them, and destroy the value.

Exercise 12-31. Write a program that uses std.ArrayList(u32). Append the numbers 1 through 10. Print their sum. Call deinit.

Exercise 12-32. Rewrite Exercise 12-31 so the ArrayList receives its allocator from a run function parameter.

Exercise 12-33. Create an arena allocator. Allocate three byte slices from it. Do not free them individually. Release all memory by deinitializing the arena.

Exercise 12-34. Use an arena allocator to build a temporary list of strings. Print the strings. Free the arena at the end.

Exercise 12-35. Explain why this function is invalid:

fn bad(parent_allocator: std.mem.Allocator) ![]u8 {
    var arena = std.heap.ArenaAllocator.init(parent_allocator);
    defer arena.deinit();

    const allocator = arena.allocator();
    return try allocator.dupe(u8, "zig");
}

Exercise 12-36. Fix Exercise 12-35 by allocating the returned string from the caller’s allocator instead of from a local arena.

Exercise 12-37. Create a fixed-buffer allocator backed by this array:

var memory: [512]u8 = undefined;

Allocate two slices from it and print their lengths.

Exercise 12-38. Use std.ArrayList(u8) with a fixed-buffer allocator. Append "hello" and " zig", then print the resulting string.

Exercise 12-39. Create a fixed-buffer allocator with only 8 bytes of backing storage. Attempt to allocate 1024 bytes. Handle the allocation error with catch.

Exercise 12-40. Write a small owned type:

const Buffer = struct {
    allocator: std.mem.Allocator,
    data: []u8,

    fn init(allocator: std.mem.Allocator, len: usize) !Buffer {
        // ...
    }

    fn deinit(self: *Buffer) void {
        // ...
    }
};

init should allocate the buffer. deinit should free it.

Exercise 12-41. Add a method to Buffer:

fn fill(self: *Buffer, value: u8) void

The method should fill the owned memory with value.

Exercise 12-42. Add a method to Buffer:

fn print(self: *const Buffer) void

The method should print the length and first byte of the buffer.

Exercise 12-43. Write a function that borrows a slice:

fn countByte(bytes: []const u8, needle: u8) usize

It should not allocate and should not free memory.

Exercise 12-44. Write a function that takes ownership of an allocated slice and frees it before returning:

fn consume(allocator: std.mem.Allocator, bytes: []u8) void

After calling consume, the caller must not use the slice.

Exercise 12-45. Write a program with one allocation bug. Then fix it. Examples: leaked memory, double free, use after free, or returning a slice to local memory.

Exercise 12-46. Write a short note explaining the difference between owning a slice and borrowing a slice.

Exercise 12-47. Write a short note explaining when to use an arena allocator.

Exercise 12-48. Write a short note explaining when to use a fixed-buffer allocator.

Exercise 12-49. Write a short note explaining why library functions should usually accept an allocator instead of choosing std.heap.page_allocator internally.

Exercise 12-50. Write a complete program that reads command-line arguments into an ArrayList([]const u8) and prints them.