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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 22:20:14