You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言双栈实现队列pop2函数运行异常无报错问题

问题根因

程序崩溃的核心原因是未初始化的野指针访问,属于典型的C语言内存非法操作:

  1. pop2函数中声明的struct stack *lol是局部指针变量,声明后没有为它分配struct stack类型的实际内存空间,指针指向随机的非法内存地址。第一行printf("!")执行时还没有触碰这个野指针所以可以正常输出,执行到lol->top1=-1时,程序尝试向非法内存地址写入数据,直接触发段错误崩溃,后续代码根本没有执行机会。
  2. 观察到只有第一个!输出,是因为C语言标准输出默认是行缓冲模式:不带换行符的打印内容会先暂存在内存缓冲区里,等攒够一行或者程序正常退出时才会刷到屏幕上。程序崩溃时缓冲区不会自动刷新,所以后续两个printf("!")的内容根本没来得及显示,程序就已经终止了。
  3. 另外main函数里的struct stack *ptr同样是未初始化的野指针,移除pop2调用后程序能运行完全是内存布局的巧合,本质还是非法操作,随时可能崩溃。
其他现存代码问题
  • 函数返回值缺失:push、pop、pop2都声明为返回int类型,但除了正常分支外,异常分支(栈满、栈空)都没有写返回值,会触发未定义行为。
  • 逻辑完全缺失:当前的pop2没有实现任何双栈实现队列的核心逻辑,结构体里定义的top1字段也没有实际用途。双栈队列的标准逻辑是:用一个栈负责入队,另一个栈负责出队,出队时如果出队栈为空,就把入队栈的所有元素依次弹出压入出队栈,此时出队栈的栈顶就是最早入队的元素。
  • 内存泄漏风险:所有malloc申请的内存使用完后没有对应free操作。
修复后完整代码
#include <stdio.h>
#include <stdlib.h>

// 栈结构定义,移除无实际用途的top1字段
struct stack {
    int top;
    int size;
    int *arr;
};

// 栈判空
int isempty(struct stack *ptr) {
    return ptr->top == -1;
}

// 栈判满
int isfull(struct stack *ptr) {
    return ptr->top == ptr->size - 1;
}

// 入栈
void push(struct stack *ptr, int data) {
    if (isfull(ptr)) {
        printf("Stack is Full\n");
        return;
    }
    ptr->top++;
    ptr->arr[ptr->top] = data;
}

// 出栈
int pop(struct stack *ptr) {
    if (isempty(ptr)) {
        printf("Stack is empty\n");
        return -1; // 栈空返回错误标识值
    }
    int val = ptr->arr[ptr->top];
    ptr->top--;
    return val;
}

// 栈初始化函数,先为栈结构体分配内存,再初始化成员
struct stack* init_stack(int size) {
    struct stack *s = (struct stack*)malloc(sizeof(struct stack));
    s->top = -1;
    s->size = size;
    s->arr = (int*)malloc(size * sizeof(int));
    return s;
}

// 双栈队列的出队操作,替换原有逻辑残缺的pop2
int dequeue(struct stack *in_stack, struct stack *out_stack) {
    // 出队栈为空时,将入队栈所有元素倒序压入出队栈
    if (isempty(out_stack)) {
        while (!isempty(in_stack)) {
            int val = pop(in_stack);
            push(out_stack, val);
        }
    }
    // 弹出出队栈栈顶即为队首元素,符合队列先进先出特性
    return pop(out_stack);
}

// 释放栈内存,避免泄漏
void free_stack(struct stack *s) {
    free(s->arr);
    free(s);
}

int main() {
    // 初始化两个栈分别作为入队栈、出队栈
    struct stack *in = init_stack(100);
    struct stack *out = init_stack(100);

    // 入队5个元素
    push(in, 1);
    push(in, 2);
    push(in, 3);
    push(in, 4);
    push(in, 5);

    // 依次出队,将按1 2 3 4 5的顺序输出
    printf("%d ", dequeue(in, out));
    printf("%d ", dequeue(in, out));
    printf("%d ", dequeue(in, out));
    printf("%d ", dequeue(in, out));
    printf("%d ", dequeue(in, out));

    // 释放申请的内存
    free_stack(in);
    free_stack(out);
    return 0;
}
修复要点说明
  • 所有栈指针使用前,必须先为struct stack结构体本身分配内存,不能直接声明指针就操作成员,从根源避免野指针。
  • 把原有逻辑残缺的pop2替换为符合双栈队列逻辑的dequeue函数,真正实现队列先进先出的特性。
  • 补全所有函数的返回逻辑,避免无返回值的未定义行为。
  • 增加栈初始化、内存释放的工具函数,保证内存操作合法,避免泄漏。
  • 调试打印如果需要即时看到输出,可以加换行符或者手动刷新缓冲区,避免崩溃时看不到打印内容。

内容的提问来源于stack exchange,提问作者Bharat Goyal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 06:00:59