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

C语言链表栈pop函数空栈调用崩溃问题求助

链表实现栈的pop函数崩溃问题排查与修复

问题现象

  • 初始空栈调用pop函数,能正常输出"Stack is empty."
  • 调用push添加元素后,多次调用pop至空栈,后续再以空栈调用pop时,程序崩溃冻结且无输出。

相关代码

stack_ll.c

#include <stdio.h>
#include <stdlib.h>
#include "stack_ll.h"

int pop(node *root){
if(root == NULL){
    printf("Stack is empty.");
    return -1;
}

if(root->next == NULL){ // 只剩一个元素时
int rvalue = root->data;
    root = NULL;
    free(root);
    return rvalue;
}

node *iter = root;
while(iter->next->next != NULL){
    iter = iter->next;
}
node * temp = iter->next;
int rvalue = temp->data;
free(temp);
iter->next = NULL;

return rvalue;
}

node* push(node * root, int a){
if(root == NULL){
    root = (node *)malloc(sizeof(node));
    root -> data = a;
    root -> next = NULL;
    return root;
}
node * iter = root;
while(iter->next != NULL){
    iter = iter->next;
}
node * temp = (node *)malloc(sizeof(node));
temp->data = a;
temp->next = NULL;
iter->next = temp;
return root;
}

test_stack_ll.c

#include <stdio.h>
#include <stdlib.h>
#include "stack_ll.h"

int main(){
node * s = NULL;
s = push(s,15);
s = push(s,25);
s = push(s,35); 
printf("%d -> ", pop(s)); // 正常工作
printf("%d -> ", pop(s)); // 正常工作
printf("%d -> ", pop(s)); // 出现问题
}

stack_ll.h

#ifndef stack_ll
#define stack_ll    

typedef struct n{
int data;
struct n *next;
}node;

int pop(node*);
node* push(node *, int);

#endif

问题根源

pop函数采用值传递接收栈顶指针root,函数内部对root的修改无法同步到主函数的栈顶指针s:

  1. 当栈中只剩最后一个元素时,函数内将局部变量root设为NULL,但主函数的s仍然指向原节点内存(未被正确释放),形成无效指针。
  2. 后续调用pop时,root(即s)不为NULL,程序会尝试访问root->next,触发未定义行为(崩溃)。
  3. 代码中root = NULL; free(root);的顺序错误,导致原节点内存泄漏(没有释放实际指向的节点,反而free了NULL)。

修复方案

修改pop函数为指针的指针传递,以便修改主函数中的栈顶指针,同时修正内存释放逻辑:

修改后的stack_ll.c(仅pop函数部分)

int pop(node **root){
if(*root == NULL){
    printf("Stack is empty.");
    return -1;
}

if((*root)->next == NULL){ // 只剩一个元素时
    int rvalue = (*root)->data;
    free(*root); // 先释放节点内存
    *root = NULL; // 再将栈顶指针置空
    return rvalue;
}

node *iter = *root;
while(iter->next->next != NULL){
    iter = iter->next;
}
node * temp = iter->next;
int rvalue = temp->data;
free(temp);
iter->next = NULL;

return rvalue;
}

修改stack_ll.h中的pop函数声明

int pop(node**);

修改test_stack_ll.c中的调用方式

printf("%d -> ", pop(&s)); // 传入栈顶指针的地址
printf("%d -> ", pop(&s));
printf("%d -> ", pop(&s));
// 后续再调用pop(&s)也能正常输出提示

修复原理

  • 通过node**传递栈顶指针,函数内部可以直接修改主函数中s的指向,确保栈空时s被置为NULL。
  • 调整内存释放顺序:先释放节点内存,再将栈顶指针置空,避免野指针和内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 20:27:14