栈Push操作为何引发段错误?如何保留双指针TOS修正出错代码?
栈Push操作引发段错误的原因及你的代码问题解析
咱们一步步来拆解你的问题,先解决通用的Push段错误原因,再针对性看你的代码问题~
首先回答第一个问题:为什么栈的Push操作会引发段错误?
常见的触发原因主要有这几个:
- 解引用空指针/野指针:比如栈顶指针没正确初始化,或者指向了无效内存区域,当你尝试访问这个指针指向的内容时,操作系统会直接抛出段错误
- 内存分配失败:如果用链表实现栈,调用
malloc/calloc时可能因内存不足返回NULL,这时候直接访问新节点的成员(比如temp->num)就会触发错误 - 数组栈溢出:如果用固定大小的数组实现栈,当Push的元素数量超过数组长度时,会越界访问内存,同样会引发段错误
接下来看你的代码为什么会出现段错误,同时满足你保留TOS作为双指针的需求:
你的代码核心问题
先看main函数里的这行定义:
NODE **TOS = NULL, *temp;
你定义了一个双指针TOS并初始化为NULL,然后直接把它传给push函数。但push函数需要的是一个指向有效NODE指针的双指针——也就是说,这个双指针得指向一个实际存在的NODE*变量,这样push才能通过它修改栈顶指针的指向。
而你现在传的是一个NULL的双指针,当push里执行temp->next = (*TOS)或者(*TOS) = temp时,本质是在对NULL指针进行解引用,这是完全非法的内存访问,操作系统直接就会触发段错误。
保留双指针的修正方案
如果你一定要保留TOS作为双指针,只需要让它指向一个有效的NODE*变量即可,下面是修正后的完整代码:
#include<stdio.h> #include<stdlib.h> typedef struct node_tag{ int num; struct node_tag* next; }NODE; void push(int x, NODE **TOS){ NODE* temp = (NODE*) malloc(sizeof(NODE)); // 一定要检查malloc是否成功!避免内存分配失败导致的段错误 if(temp == NULL){ fprintf(stderr, "内存分配失败!\n"); exit(EXIT_FAILURE); } temp->num = x; temp->next = (*TOS); (*TOS) = temp; } int main(){ // 先定义一个普通的栈顶指针,初始化为NULL NODE *top_ptr = NULL; // 让双指针TOS指向这个普通指针 NODE **TOS = &top_ptr; printf("<<<Stack Push>>>"); push(0, TOS); printf("%i", (*TOS)->num); // 别忘了释放内存,避免内存泄漏 NODE* temp = *TOS; *TOS = (*TOS)->next; free(temp); return 0; }
更常规的写法(同样符合双指针传参逻辑)
其实日常写链表栈时,大部分情况会直接在main里定义普通的栈顶指针,然后传它的地址给push函数,本质和上面的逻辑一致,只是少了一层双指针的显式定义:
#include<stdio.h> #include<stdlib.h> typedef struct node_tag{ int num; struct node_tag* next; }NODE; void push(int x, NODE **TOS){ NODE* temp = (NODE*) malloc(sizeof(NODE)); if(temp == NULL){ fprintf(stderr, "内存分配失败!\n"); exit(EXIT_FAILURE); } temp->num = x; temp->next = (*TOS); (*TOS) = temp; } int main(){ NODE *TOS = NULL; printf("<<<Stack Push>>>"); // 传普通指针的地址,也就是NODE**类型 push(0, &TOS); printf("%i", TOS->num); // 释放内存 NODE* temp = TOS; TOS = TOS->next; free(temp); return 0; }
最后再提个醒:任何时候调用malloc都要检查返回值,不然遇到内存不足的情况,你的代码还是会触发段错误哦~
内容的提问来源于stack exchange,提问作者Jsandesu
相关产品推荐
相关产品推荐

