krahets/hello-algo · error

佇列為空

Error message

佇列為空

What it means

Unrecoverable Zig @panic from peek() on the circular array queue. Guard `if (self.isEmpty()) @panic("佇列為空")` runs before `return self.nums[self.front]`, so it prevents reading an undefined slot in the backing array. The queue treats peeking the head of an empty queue as a programming error.

Source

Thrown at zh-hant/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. Gate every peek()/pop() on `if (!q.isEmpty())` (or `q.size() > 0`).
  2. Restructure the consumer to loop `while (!q.isEmpty()) { ... q.pop(); }` so no peek occurs at size 0.
  3. Wrap the queue with a peek()-returning-?T adapter if empty-head inspection is legitimate.

Example fix

// before
var n = q.pop();      // pop() internally peeks -> panic
// after
if (q.isEmpty()) return null;
var n = q.pop();
Defensive patterns

Strategy: validation

Validate before calling

// call BEFORE peek()/pop()  (pop() delegates to peek())
if (q.isEmpty()) return null;
var n = q.pop();

Prevention

When it happens

Trigger: Call peek() (directly or via pop(), which calls peek() internally) on an ArrayQueue with queSize == 0 — freshly constructed, or after every element has been popped. Because pop() delegates to peek(), popping an empty queue surfaces this same panic rather than pop's own message.

Common situations: Consumer loops that pop/peek without an isEmpty gate; polling a queue before the first enqueue; round-robin schedulers that peek the head before any task is queued.

Related errors


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