krahets/hello-algo · error

队列为空

Error message

队列为空

What it means

@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.

Source

Thrown at codes/zig/chapter_stack_and_queue/array_queue.zig:77

            // 通过取余操作实现 rear 越过数组尾部后回到头部
            var rear = (self.front + self.queSize) % self.capacity();
            // 在尾节点后添加 num
            self.nums[rear] = num;
            self.queSize += 1;
        } 

        // 出队
        pub fn pop(self: *Self) T {
            var num = self.peek();
            // 队首指针向后移动一位,若越过尾部,则返回到数组头部
            self.front = (self.front + 1) % self.capacity();
            self.queSize -= 1;
            return num;
        } 

        // 访问队首元素
        pub fn peek(self: *Self) T {
            if (self.isEmpty()) @panic("队列为空");
            return self.nums[self.front];
        } 

        // 返回数组
        pub fn toArray(self: *Self) ![]T {
            // 仅转换有效长度范围内的列表元素
            var res = try self.mem_allocator.alloc(T, self.size());
            @memset(res, @as(T, 0));
            var i: usize = 0;
            var j: usize = self.front;
            while (i < self.size()) : ({ i += 1; j += 1; }) {
                res[i] = self.nums[j % self.capacity()];
            }
            return res;
        }
    };
}

View on GitHub (pinned to 69932aed18)

Solutions

  1. Call isEmpty() and branch before peek()/pop(); do not peek or pop when empty.
  2. In drain loops, loop `while (!q.isEmpty())` rather than a fixed count.
  3. Track the expected element count externally and stop popping when it hits zero.
  4. Add a safe wrapper returning an optional/error instead of panicking.

Example fix

// before: @panics '队列为空' on empty queue
const v = queue.peek();
const w = queue.pop();

// after
if (!queue.isEmpty()) {
    const v = queue.peek();
    const w = queue.pop();
}
Defensive patterns

Strategy: validation

Validate before calling

// Covers both peek() and pop() (pop delegates to peek).
if (!queue.isEmpty()) {
    const v = queue.peek();
    const w = queue.pop();
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of krahets/hello-algo@69932aed18 (2026-08-13). Data as JSON: /api/errors/e840a173133b5e2c. Report an issue: GitHub.