{"record":{"id":"330e1fb4d44c6e2c","repo":"krahets/hello-algo","slug":"error-330e1f","errorCode":null,"errorMessage":"堆疊為空","messagePattern":"堆疊為空","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"zh-hant/codes/zig/chapter_stack_and_queue/array_stack.zig","lineNumber":40,"sourceCode":"        // 析構方法（釋放記憶體）\n        pub fn deinit(self: *Self) void {\n            if (self.stack == null) return;\n            self.stack.?.deinit();\n        }\n\n        // 獲取堆疊的長度\n        pub fn size(self: *Self) usize {\n            return self.stack.?.items.len;\n        }\n\n        // 判斷堆疊是否為空\n        pub fn isEmpty(self: *Self) bool {\n            return self.size() == 0;\n        }\n\n        // 訪問堆疊頂元素\n        pub fn peek(self: *Self) T {\n            if (self.isEmpty()) @panic(\"堆疊為空\");\n            return self.stack.?.items[self.size() - 1];\n        }  \n\n        // 入堆疊\n        pub fn push(self: *Self, num: T) !void {\n            try self.stack.?.append(num);\n        } \n\n        // 出堆疊\n        pub fn pop(self: *Self) T {\n            var num = self.stack.?.pop();\n            return num;\n        } \n\n        // 返回 ArrayList\n        pub fn toList(self: *Self) std.ArrayList(T) {\n            return self.stack.?;\n        }","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/krahets/hello-algo/blob/69932aed1891a7b7f6a0de88cd116d3fe13e7032/zh-hant/codes/zig/chapter_stack_and_queue/array_stack.zig#L22-L58","documentation":"Unrecoverable Zig @panic from peek() on the array-backed stack. Guard `if (self.isEmpty()) @panic(\"堆疊為空\")` runs before `return self.stack.?.items[self.size() - 1]`; without it, self.size()-1 would underflow (usize wrap) on an empty stack. The stack defines peeking an empty top as a caller logic error.","triggerScenarios":"Call peek() on an ArrayStack with zero elements: never pushed, or fully popped. The guard is essential here because the alternative is a usize underflow on `size - 1`, which would be a silent memory-safety violation.","commonSituations":"Expression evaluators that peek for a pending operator before the first push; parsers that peek the symbol stack after it empties; tests that assert on the top of a newly constructed stack; backtracking that peeks the work stack after draining it.","solutions":["Prepend `if (!stk.isEmpty())` before every peek().","Drive the algorithm so peek() only runs in a branch that already established size() > 0.","Provide a safe wrapper returning ?T for empty-top cases."],"exampleFix":"// before\nconst top = stk.peek();\n// after\nconst top = if (stk.isEmpty()) null else stk.peek();","handlingStrategy":"validation","validationCode":"// call BEFORE peek()\nif (stk.isEmpty()) return null;\nconst top = stk.peek();","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always gate peek() on isEmpty() — without it, size()-1 underflows on usize.","Restructure evaluators so the top is only peeked after a guaranteed push.","Provide a ?T-returning wrapper for empty-top cases."],"tags":["zig","stack","peek","data-structure","empty-state","usize-underflow"],"backgroundTag":null,"analyzedSha":"69932aed1891a7b7f6a0de88cd116d3fe13e7032","analyzedAt":"2026-08-13T23:02:37.581Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}