# `defer` and `errdefer`

### `defer` and `errdefer`

A program that opens a file must close it. A program that allocates memory must free it. A program that locks a mutex must unlock it.

Zig uses `defer` for this kind of cleanup.

```zig
const file = try std.fs.cwd().openFile("data.txt", .{});
defer file.close();
```

The `defer` statement runs when the current scope exits.

This matters because a scope may exit in more than one way. It may reach the end. It may return a value. It may return an error.

```zig
const std = @import("std");

fn showFile() !void {
    const file = try std.fs.cwd().openFile("data.txt", .{});
    defer file.close();

    var buf: [128]u8 = undefined;
    const n = try file.read(&buf);

    std.debug.print("{s}\n", .{buf[0..n]});
}

pub fn main() !void {
    try showFile();
}
```

If `file.read` succeeds, the file is closed before `showFile` returns.

If `file.read` fails, the file is still closed before the error leaves `showFile`.

That is the point of `defer`: cleanup is placed next to the resource it cleans up.

The old style is fragile:

```zig
const file = try std.fs.cwd().openFile("data.txt", .{});

var buf: [128]u8 = undefined;
const n = try file.read(&buf);

file.close();
```

If `file.read` fails, execution skips the final `file.close()`. The resource leaks.

With `defer`, the close operation is registered immediately:

```zig
const file = try std.fs.cwd().openFile("data.txt", .{});
defer file.close();
```

A `defer` runs at the end of its enclosing block, not necessarily at the end of the function.

```zig
{
    const file = try std.fs.cwd().openFile("data.txt", .{});
    defer file.close();

    // use file here
}

// file is already closed here
```

Multiple `defer` statements run in reverse order.

```zig
defer std.debug.print("first\n", .{});
defer std.debug.print("second\n", .{});
defer std.debug.print("third\n", .{});
```

This prints:

```text
third
second
first
```

The reverse order is deliberate. It matches the order in which resources are usually acquired.

```zig
const a = try openA();
defer closeA(a);

const b = try openB();
defer closeB(b);
```

`b` is closed first, then `a`.

`errdefer` is similar, but it runs only when the scope exits with an error.

This is useful for ownership transfer.

```zig
const std = @import("std");

fn makeBuffer(allocator: std.mem.Allocator) ![]u8 {
    const buf = try allocator.alloc(u8, 1024);
    errdefer allocator.free(buf);

    // more work may fail here

    return buf;
}
```

If allocation succeeds and later work fails, `errdefer` frees the buffer.

If the function succeeds, `errdefer` does not run. The buffer is returned to the caller, and the caller now owns it.

This is different from `defer`.

```zig
fn wrong(allocator: std.mem.Allocator) ![]u8 {
    const buf = try allocator.alloc(u8, 1024);
    defer allocator.free(buf);

    return buf;
}
```

This function returns a slice to memory that has already been freed. The `defer` runs when the function returns, even on success.

For returned resources, use `errdefer` until ownership has been transferred.

A common allocation pattern is:

```zig
fn makeThing(allocator: std.mem.Allocator) !Thing {
    var thing = Thing{};
    errdefer thing.deinit(allocator);

    try thing.addPart(allocator);
    try thing.addOtherPart(allocator);

    return thing;
}
```

If either `addPart` or `addOtherPart` fails, the partially-built value is destroyed. If everything succeeds, the caller receives the value and must later call `deinit`.

`errdefer` may also capture the error:

```zig
fn run() !void {
    errdefer |err| std.debug.print("failed: {}\n", .{err});

    try stepOne();
    try stepTwo();
}
```

If `stepOne` or `stepTwo` fails, the error is printed before it is returned.

Use this carefully. Logging every low-level error can make programs noisy. It is usually better to log at the boundary where the program can explain what operation failed.

The rule is simple:

`defer` runs when the scope exits.

`errdefer` runs only when the scope exits with an error.

Use `defer` for resources that must always be released.

Use `errdefer` for resources that must be released only if construction fails.

Exercise 8-21. Open a file and close it with `defer`.

Exercise 8-22. Allocate a buffer and free it with `defer`.

Exercise 8-23. Write a function that allocates a buffer and returns it. Use `errdefer`.

Exercise 8-24. Add two `defer` statements and observe their order.

