Zig defer 慣用法
原文地址:Zig defer Patterns[1]
裏面講述了 defer 除了做資源回收外,其他的一些慣用法,裏面有幾個有趣的點。
第一點是這個:
errdefer comptime unreachable
文中稱這個是 Zig 的巔峯用法😅, errdefer unreachable
還比較好理解,即在執行出錯時,執行 unreachable ,那加上 comptime 呢?
其實這是阻止 Zig 編譯器生產錯誤處理的代碼,即在編譯時期保證下面的邏輯不會出錯,確實用的很巧妙!一個簡單的例子來說明:
const std = @import("std");
test "errdeferWithUnreachable" {
errdefer comptime unreachable;
const i = try inc(1);
std.testing.expectEqual(i, 2);
}
fn inc(a: i8) !i8 {
if (a > 10) {
return error.TooLarge;
}
return a + 1;
}
直接執行 zig test
,在編譯時會報下面的錯誤:
test.zig:4:23: error: reached unreachable code
errdefer comptime unreachable;
雖然 a
是個運行時的值,但是 errdefer comptime unreachable
不關心這個,只要 Zig 編譯器開始生成 ErrorSet 相關代碼路徑,編譯就會報錯,去掉上面的 if 判斷測試就可以正常運行。 一個很好的實際例子:std.hash_map: fix pointer lock safety false positive by andrewrk · Pull Request #19364 · ziglang/zig[2]
assert(std.math.isPowerOfTwo(new_cap));
var map: Self = .{};
- defer map.deinit(allocator);
- map.pointer_stability.lock();
try map.allocate(allocator, new_cap);
+ errdefer comptime unreachable;
+ map.pointer_stability.lock();
map.initMetadatas();
map.available = @truncate((new_cap * max_load_percentage) / 100);
@@6581,7 @@ pub fn HashMapUnmanaged(
self.size = 0;
self.pointer_stability = .{ .state = .unlocked };
std.mem.swap(Self, self, &map);
+ map.deinit(allocator);
+
+test "getOrPut allocation failure" {
+ var map: std.StringHashMapUnmanaged(void) = .{};
+ try testing.expectError(error.OutOfMemory, map.getOrPut(std.testing.failing_allocator, "hello"));
+}
可以看到, 這麼修改後,就可以保證 map.deinit(allocator);
語句之前沒有錯誤可能產生!讀者可以細細品味一下這個用法。
另一個小技巧是 errdefer 竟然支持錯誤捕獲,即下面這種用法:
const port = port: {
errdefer |err| std.log.err("failed to read the port number: {!}", .{err});
var buf: [fmt.count("{}\n", .{maxInt(u16)})]u8 = undefined;
const len = try process.stdout.?.readAll(&buf);
break :port try fmt.parseInt(u16, buf[0 .. len -| 1], 10);
};
ZigCC
-
• 日報地址:https://github.com/zigcc/forum/issues/108
-
• 論壇地址:https://github.com/orgs/zigcc/discussions
引用鏈接
[1]
Zig defer Patterns: https://matklad.github.io/2024/03/21/defer-patterns.html
[2]
std.hash_map: fix pointer lock safety false positive by andrewrk · Pull Request #19364 · ziglang/zig: https://github.com/ziglang/zig/pull/19364/files
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/dLniqksAjHrErJ6mLhDiNw