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:
- 当栈中只剩最后一个元素时,函数内将局部变量
root设为NULL,但主函数的s仍然指向原节点内存(未被正确释放),形成无效指针。 - 后续调用
pop时,root(即s)不为NULL,程序会尝试访问root->next,触发未定义行为(崩溃)。 - 代码中
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
相关产品推荐
相关产品推荐

