Commit 3ce6de8765
Changed files (5)
doc/langref/test_errdefer_block.zig
@@ -1,42 +0,0 @@
-const std = @import("std");
-const Allocator = std.mem.Allocator;
-
-const Foo = struct {
- data: u32,
-};
-
-fn tryToAllocateFoo(allocator: Allocator) !*Foo {
- return allocator.create(Foo);
-}
-
-fn deallocateFoo(allocator: Allocator, foo: *Foo) void {
- allocator.destroy(foo);
-}
-
-fn getFooData() !u32 {
- return 666;
-}
-
-fn createFoo(allocator: Allocator, param: i32) !*Foo {
- const foo = getFoo: {
- var foo = try tryToAllocateFoo(allocator);
- errdefer deallocateFoo(allocator, foo);
-
- foo.data = try getFooData();
-
- break :getFoo foo;
- };
- // This lasts for the rest of the function
- errdefer deallocateFoo(allocator, foo);
-
- // Error is now properly handled by errdefer
- if (param > 1337) return error.InvalidParam;
-
- return foo;
-}
-
-test "createFoo" {
- try std.testing.expectError(error.InvalidParam, createFoo(std.testing.allocator, 2468));
-}
-
-// test
doc/langref/test_errdefer_loop.zig
@@ -1,36 +0,0 @@
-const std = @import("std");
-const Allocator = std.mem.Allocator;
-
-const Foo = struct { data: *u32 };
-
-fn getData() !u32 {
- return 666;
-}
-
-fn genFoos(allocator: Allocator, num: usize) ![]Foo {
- const foos = try allocator.alloc(Foo, num);
- errdefer allocator.free(foos);
-
- // Used to track how many foos have been initialized
- // (including their data being allocated)
- var num_allocated: usize = 0;
- errdefer for (foos[0..num_allocated]) |foo| {
- allocator.destroy(foo.data);
- };
- for (foos, 0..) |*foo, i| {
- foo.data = try allocator.create(u32);
- num_allocated += 1;
-
- if (i >= 3) return error.TooManyFoos;
-
- foo.data.* = try getData();
- }
-
- return foos;
-}
-
-test "genFoos" {
- try std.testing.expectError(error.TooManyFoos, genFoos(std.testing.allocator, 5));
-}
-
-// test
doc/langref/test_errdefer_loop_leak.zig
@@ -1,32 +0,0 @@
-const std = @import("std");
-const Allocator = std.mem.Allocator;
-
-const Foo = struct { data: *u32 };
-
-fn getData() !u32 {
- return 666;
-}
-
-fn genFoos(allocator: Allocator, num: usize) ![]Foo {
- const foos = try allocator.alloc(Foo, num);
- errdefer allocator.free(foos);
-
- for (foos, 0..) |*foo, i| {
- foo.data = try allocator.create(u32);
- // This errdefer does not last between iterations
- errdefer allocator.destroy(foo.data);
-
- // The data for the first 3 foos will be leaked
- if (i >= 3) return error.TooManyFoos;
-
- foo.data.* = try getData();
- }
-
- return foos;
-}
-
-test "genFoos" {
- try std.testing.expectError(error.TooManyFoos, genFoos(std.testing.allocator, 5));
-}
-
-// test_error=3 errors were logged
doc/langref/test_errdefer_slip_ups.zig
@@ -1,42 +0,0 @@
-const std = @import("std");
-const Allocator = std.mem.Allocator;
-
-const Foo = struct {
- data: u32,
-};
-
-fn tryToAllocateFoo(allocator: Allocator) !*Foo {
- return allocator.create(Foo);
-}
-
-fn deallocateFoo(allocator: Allocator, foo: *Foo) void {
- allocator.destroy(foo);
-}
-
-fn getFooData() !u32 {
- return 666;
-}
-
-fn createFoo(allocator: Allocator, param: i32) !*Foo {
- const foo = getFoo: {
- var foo = try tryToAllocateFoo(allocator);
- errdefer deallocateFoo(allocator, foo); // Only lasts until the end of getFoo
-
- // Calls deallocateFoo on error
- foo.data = try getFooData();
-
- break :getFoo foo;
- };
-
- // Outside of the scope of the errdefer, so
- // deallocateFoo will not be called here
- if (param > 1337) return error.InvalidParam;
-
- return foo;
-}
-
-test "createFoo" {
- try std.testing.expectError(error.InvalidParam, createFoo(std.testing.allocator, 2468));
-}
-
-// test_error=1 tests leaked memory
doc/langref.html.in
@@ -3052,32 +3052,6 @@ fn createFoo(param: i32) !Foo {
The {#syntax#}errdefer{#endsyntax#} statement can optionally capture the error:
</p>
{#code|test_errdefer_capture.zig#}
- {#header_close#}
- {#header_open|Common errdefer Slip-Ups#}
- <p>
- It should be noted that {#syntax#}errdefer{#endsyntax#} statements only last until the end of the block
- they are written in, and therefore are not run if an error is returned outside of that block:
- </p>
- {#code|test_errdefer_slip_ups.zig#}
-
- <p>
- To ensure that {#syntax#}deallocateFoo{#endsyntax#} is properly called
- when returning an error, you must add an {#syntax#}errdefer{#endsyntax#} outside of the block:
- </p>
- {#code|test_errdefer_block.zig#}
-
- <p>
- The fact that errdefers only last for the block they are declared in is
- especially important when using loops:
- </p>
- {#code|test_errdefer_loop_leak.zig#}
-
- <p>
- Special care must be taken with code that allocates in a loop
- to make sure that no memory is leaked when returning an error:
- </p>
- {#code|test_errdefer_loop.zig#}
-
{#header_close#}
<p>
A couple of other tidbits about error handling: