krahets/hello-algo · error

双向队列为空

Error message

双向队列为空

What it means

@panic in pop(is_front) of the Zig LinkedListDeque when the deque is empty. pop() must dereference front or rear to retrieve a value, which is invalid when the deque holds no nodes, so it aborts with '双向队列为空' (deque is empty). Both popFirst() and popLast() delegate to pop(), so they share this panic. @panic in Zig is unrecoverable and terminates the process.

Source

Thrown at codes/zig/chapter_stack_and_queue/linkedlist_deque.zig:100

                node.prev = self.rear;
                self.rear = node;   // 更新尾节点
            }
            self.que_size += 1;      // 更新队列长度
        } 

        // 队首入队
        pub fn pushFirst(self: *Self, num: T) !void {
            try self.push(num, true);
        } 

        // 队尾入队
        pub fn pushLast(self: *Self, num: T) !void {
            try self.push(num, false);
        } 
        
        // 出队操作
        pub fn pop(self: *Self, is_front: bool) T {
            if (self.isEmpty()) @panic("双向队列为空");
            var val: T = undefined;
            // 队首出队操作
            if (is_front) {
                val = self.front.?.val;     // 暂存头节点值
                // 删除头节点
                var fNext = self.front.?.next;
                if (fNext != null) {
                    fNext.?.prev = null;
                    self.front.?.next = null;
                }
                self.front = fNext;         // 更新头节点
            // 队尾出队操作
            } else {
                val = self.rear.?.val;      // 暂存尾节点值
                // 删除尾节点
                var rPrev = self.rear.?.prev;
                if (rPrev != null) {
                    rPrev.?.next = null;

View on GitHub (pinned to 69932aed18)

Solutions

  1. Call isEmpty() before popFirst()/popLast(); never pop when empty.
  2. Loop with `while (!deque.isEmpty())` for full drains.
  3. Track the live count externally and gate pops on it.
  4. Provide a safe wrapper returning ?T / an error for empty pops.

Example fix

// before: @panics '双向队列为空' on empty deque
const v = deque.popFirst();

// after
if (!deque.isEmpty()) {
    const v = deque.popFirst();
}
Defensive patterns

Strategy: validation

Validate before calling

// Covers popFirst()/popLast() — both delegate to pop().
if (!deque.isEmpty()) {
    const v = deque.popFirst();
}

Prevention

When it happens

Trigger: Calling popFirst()/popLast() on a freshly initialized deque with no pushes; popping after draining all elements; a work-stealing loop that pops more items than were pushed.

Common situations: Task deques where consumers outpace producers; replaying a pop sequence longer than the push sequence; assuming popFirst is independently safe because popLast already emptied the deque.

Related errors


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