zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 3ce6de87657e67da358e9c7869a87c61cc9f1305 (tree)
parent 11bf2d92de5f335d4e07358d99f26fae08493f12
Author: Andrew Kelley <andrew@ziglang.org>
Date:   Tue, 26 Nov 2024 15:03:24 -0800

revert langref section "common errdefer slip ups"

This does not belong in the language reference.

reverts 91a88a789ffa80ebb57c77ae0fe37594276e3707

Diffstat:
Mdoc/langref.html.in | 26--------------------------
Ddoc/langref/test_errdefer_block.zig | 42------------------------------------------
Ddoc/langref/test_errdefer_loop.zig | 36------------------------------------
Ddoc/langref/test_errdefer_loop_leak.zig | 32--------------------------------
Ddoc/langref/test_errdefer_slip_ups.zig | 42------------------------------------------
5 files changed, 0 insertions(+), 178 deletions(-)

diff --git a/doc/langref.html.in b/doc/langref.html.in @@ -3053,32 +3053,6 @@ fn createFoo(param: i32) !Foo { </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: </p> diff --git a/doc/langref/test_errdefer_block.zig b/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 diff --git a/doc/langref/test_errdefer_loop.zig b/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 diff --git a/doc/langref/test_errdefer_loop_leak.zig b/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 diff --git a/doc/langref/test_errdefer_slip_ups.zig b/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