C语言栈实现中删除printf后数据异常及段错误问题咨询
C语言栈实现的内存错误分析:删除printf后数据异常与段错误原因
问题场景
在学习C语言内存管理并实现栈(Stack)数据结构时,遇到两个异常现象:
- 删除某条调试用
printf语句后,栈内数据出现异常; - 直接调用
printf("%d", pop_pilha(nova_pilha))会触发segmentation fault(段错误)。
相关代码(葡萄牙语标识符已标注中文含义):
#include <stdio.h> #include <stdlib.h> typedef struct { int *arr; size_t size; unsigned int index; }Pilha; Pilha* criar_pilha(size_t size){ //"criar_pilha" = create_stack int array[size]; Pilha* pilha_f = malloc(sizeof(Pilha)); //"pilha_f" = stack_f pilha_f->size = size; pilha_f->arr = array; pilha_f->index = 0; return pilha_f; } void push_pilha(Pilha* pilha_f,int valor){ //"valor" = value if (!(pilha_f->size-1< pilha_f->index)) { pilha_f->arr[pilha_f->index] = valor; pilha_f->index++; } } int pop_pilha(Pilha* pilha_f){ int valor; if ( (pilha_f->index-1) < 0) { return NULL; }else{ pilha_f->index= pilha_f->index-1; //printf("%d",pilha_f->index); valor = pilha_f->arr[pilha_f->index]; } return valor; } int main(){ Pilha* nova_pilha = criar_pilha(3);// "nova_pilha" = new_stack int temp; printf("pilha criada com sucssso");// 删除此printf后出现异常 push_pilha(nova_pilha,4); push_pilha(nova_pilha,5); push_pilha(nova_pilha,72); temp = pop_pilha(nova_pilha); printf("\n%d",temp); temp = pop_pilha(nova_pilha); printf("\n%d",temp); temp = pop_pilha(nova_pilha); printf("\n%d",temp); free(nova_pilha); return 0; }
输出情况
- 保留该
printf时输出正常:
pilha criada com sucesso 72 5 4
- 删除该
printf后输出异常:
72 0 0
使用环境:Archcraft(Linux)、gcc 13.2.1
错误根源
1. 野指针导致的非法内存访问
criar_pilha函数中,int array[size]是栈上的局部变量。当函数执行完毕返回时,当前函数的栈帧会被销毁,这块数组内存会被操作系统标记为可复用。此时返回的Pilha结构体中,arr指针指向的是已经失效的内存,属于野指针。
- 保留
printf时看似正常,是因为printf函数的栈帧恰好没有覆盖之前的局部数组内存,属于偶然的内存残留; - 删除
printf后,后续调用push_pilha时的栈操作会覆盖这块失效内存,导致之前存入的数据被破坏,最终输出异常。
2. 类型不匹配与栈空判断错误
pop_pilha函数的返回类型是int,但栈空时返回NULL(本质是值为0的指针),这属于类型不匹配,会导致未定义行为;- 栈空判断条件
(pilha_f->index-1) < 0存在逻辑错误:index是unsigned int类型,当index为0时,index-1会发生无符号整数溢出,结果是一个极大的正数,永远不会小于0,导致栈空时仍会执行内存访问,触发段错误。
代码修复方案
1. 正确分配堆内存存储栈数据
将局部数组改为堆上动态分配,确保函数返回后内存仍然有效:
Pilha* criar_pilha(size_t size){ //"criar_pilha" = create_stack Pilha* pilha_f = malloc(sizeof(Pilha)); if (pilha_f == NULL) { // 检查内存分配是否成功 return NULL; } // 动态分配栈存储数组 pilha_f->arr = malloc(size * sizeof(int)); if (pilha_f->arr == NULL) { free(pilha_f); // 避免内存泄漏 return NULL; } pilha_f->size = size; pilha_f->index = 0; return pilha_f; }
2. 修复pop函数的逻辑错误
修改栈空判断逻辑,并用合理的方式返回错误状态:
// 通过指针参数返回弹出的值,返回1表示成功,0表示栈空 int pop_pilha(Pilha* pilha_f, int* valor){ if (pilha_f == NULL || valor == NULL) { return 0; } if (pilha_f->index == 0) { // 直接判断index是否为0,避免无符号溢出 return 0; } pilha_f->index--; *valor = pilha_f->arr[pilha_f->index]; return 1; }
3. 补充内存释放逻辑
在main函数中,需要先释放栈数组,再释放结构体,避免内存泄漏:
int main(){ Pilha* nova_pilha = criar_pilha(3); if (nova_pilha == NULL) { printf("栈创建失败\n"); return 1; } int temp; push_pilha(nova_pilha,4); push_pilha(nova_pilha,5); push_pilha(nova_pilha,72); if (pop_pilha(nova_pilha, &temp)) { printf("\n%d",temp); } if (pop_pilha(nova_pilha, &temp)) { printf("\n%d",temp); } if (pop_pilha(nova_pilha, &temp)) { printf("\n%d",temp); } // 释放内存 free(nova_pilha->arr); free(nova_pilha); return 0; }
内容的提问来源于stack exchange,提问作者KalebSUS
相关产品推荐
相关产品推荐

