{"record":{"id":"e840a173133b5e2c","repo":"krahets/hello-algo","slug":"error-e840a1","errorCode":null,"errorMessage":"队列为空","messagePattern":"队列为空","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"codes/zig/chapter_stack_and_queue/array_queue.zig","lineNumber":77,"sourceCode":"            // 通过取余操作实现 rear 越过数组尾部后回到头部\n            var rear = (self.front + self.queSize) % self.capacity();\n            // 在尾节点后添加 num\n            self.nums[rear] = num;\n            self.queSize += 1;\n        } \n\n        // 出队\n        pub fn pop(self: *Self) T {\n            var num = self.peek();\n            // 队首指针向后移动一位，若越过尾部，则返回到数组头部\n            self.front = (self.front + 1) % self.capacity();\n            self.queSize -= 1;\n            return num;\n        } \n\n        // 访问队首元素\n        pub fn peek(self: *Self) T {\n            if (self.isEmpty()) @panic(\"队列为空\");\n            return self.nums[self.front];\n        } \n\n        // 返回数组\n        pub fn toArray(self: *Self) ![]T {\n            // 仅转换有效长度范围内的列表元素\n            var res = try self.mem_allocator.alloc(T, self.size());\n            @memset(res, @as(T, 0));\n            var i: usize = 0;\n            var j: usize = self.front;\n            while (i < self.size()) : ({ i += 1; j += 1; }) {\n                res[i] = self.nums[j % self.capacity()];\n            }\n            return res;\n        }\n    };\n}\n","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/krahets/hello-algo/blob/69932aed1891a7b7f6a0de88cd116d3fe13e7032/codes/zig/chapter_stack_and_queue/array_queue.zig#L59-L95","documentation":"@panic in peek() of the Zig ring-buffer ArrayQueue when the queue is empty. peek() reads nums[front], which is meaningless when queSize == 0, so it aborts with '队列为空' (queue is empty). Importantly, pop() calls peek() first, so popping an empty queue panics here too. Zig @panic is unrecoverable and aborts the process.","triggerScenarios":"Calling peek() or pop() on a freshly initialized queue with no pushes; draining all elements then peeking/popping once more; a pipeline step that consumes the last element followed by another step that peeks.","commonSituations":"Producer/consumer where the consumer outruns the producer; replaying a sequence of pops that exceeds pushes; forgetting that pop() internally depends on peek() and thus shares the same panic.","solutions":["Call isEmpty() and branch before peek()/pop(); do not peek or pop when empty.","In drain loops, loop `while (!q.isEmpty())` rather than a fixed count.","Track the expected element count externally and stop popping when it hits zero.","Add a safe wrapper returning an optional/error instead of panicking."],"exampleFix":"// before: @panics '队列为空' on empty queue\nconst v = queue.peek();\nconst w = queue.pop();\n\n// after\nif (!queue.isEmpty()) {\n    const v = queue.peek();\n    const w = queue.pop();\n}","handlingStrategy":"validation","validationCode":"// Covers both peek() and pop() (pop delegates to peek).\nif (!queue.isEmpty()) {\n    const v = queue.peek();\n    const w = queue.pop();\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Zig @panic aborts the process — always call isEmpty() before peek()/pop().","Remember pop() internally calls peek(), so it shares the empty-queue panic.","Drain with `while (!q.isEmpty())` instead of a fixed iteration count."],"tags":["zig","queue","empty-state","peek","pop","validation"],"backgroundTag":null,"analyzedSha":"69932aed1891a7b7f6a0de88cd116d3fe13e7032","analyzedAt":"2026-08-13T23:02:37.581Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}