Created
January 28, 2022 17:58
-
-
Save oconnor663/7fa4bc3b44546707a9977c62a7ce6f48 to your computer and use it in GitHub Desktop.
An example of how defer/errdefer interacts with ownership.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const std = @import("std"); | |
const Allocator = std.mem.Allocator; | |
const ArrayList = std.ArrayList; | |
const Person = struct { | |
pet: Pet, | |
const Self = @This(); | |
// Takes ownership of pet. | |
pub fn init(pet: Pet) !Self { | |
return Self{ .pet = pet }; | |
} | |
pub fn deinit(self: *Self) void { | |
self.pet.deinit(); | |
} | |
const PlayError = error{ | |
Oops, | |
}; | |
pub fn play_with_pet(self: *Self) PlayError!void { | |
std.debug.print("{s}\n", .{self.pet.sound}); | |
if (std.crypto.random.boolean()) { | |
return PlayError.Oops; | |
} | |
} | |
}; | |
const Pet = struct { | |
sound: []u8, | |
const Self = @This(); | |
pub fn init() !Self { | |
return Self{ | |
.sound = try std.fmt.allocPrint( | |
std.heap.c_allocator, | |
"woof", | |
.{}, | |
), | |
}; | |
} | |
pub fn deinit(self: *Self) void { | |
std.heap.c_allocator.free(self.sound); | |
} | |
}; | |
pub fn main() !void { | |
var fido = try Pet.init(); | |
errdefer fido.deinit(); | |
// Alice takes ownership of Fido. | |
var alice = try Person.init(fido); | |
defer alice.deinit(); | |
try alice.play_with_pet(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This program crashes with a double-free when
play_with_pet
fails on line 59.