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

C语言栈实现中malloc与free操作的错误排查求助

栈实现的C语言代码错误排查与修复

问题描述

尝试编写C语言代码实现将点坐标动态存入栈,再打印并释放数据,但运行时出现以下问题:

  • 程序能打印最后一个条目,打印倒数第二个时弹出“要释放的指针未分配”错误
  • 移除free()语句后,仅打印第一行数据,随后无限输出0值
  • 将stacktop改为非静态指针也无法解决问题

原代码如下:

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

struct point{
    float x;
    float y;
    float z;
}; typedef struct point POINT;

struct stackPoint{
POINT myPoint;
struct stackPoint *next;
}; typedef struct stackPoint STACKPOINT;

static STACKPOINT *stacktop = NULL;

void printStackElement(POINT aPoint){
printf(" x:%f \t y:%f \t z:%f\n", aPoint.x, aPoint.y, aPoint.z );
}

void push(POINT pushPoint){
STACKPOINT *newElem = malloc(sizeof(STACKPOINT));
stacktop = stacktop +1;
newElem->myPoint = pushPoint;
stacktop = newElem;
}

POINT pop(){
    POINT b = stacktop->myPoint;
    free(stacktop);
    stacktop = stacktop -1;
    return b;
}

int isEmpty(){
    if(stacktop == NULL){
        return 1;
    }
    return 0;
}

POINT readPoint(){
    POINT a;
    printf("Please enter your x-Coordinate: ");
    scanf(" %f", &a.x);
    printf("Please enter your y-Coordinate: ");
    scanf(" %f", &a.y);
    printf("Please enter your z-Coordinate: ");
    scanf(" %f", &a.z);
    return a;
}

int main(){
    char quit = 0;
    while(quit !=1 ){
        printf("\n\n enter 'p' to enter another Point or 'q' to quit: ");
        scanf(" %s", &quit);
        switch(quit){
            case 'p':
                push(readPoint());
                break;
            
            case 'q':
                quit = 1;
                break;

            default:
                break;
        }
    }
    while(isEmpty() == 0){
        printStackElement(pop());
    }
}

错误分析与修复

1. 链表栈指针操作逻辑错误(核心问题)

代码混淆了数组栈和链表栈的实现逻辑:

  • push函数中stacktop = stacktop +1;:指针直接加1会指向当前节点内存地址的下一块未知区域,并非链表的下一个节点,直接断裂栈的链表结构,后续访问均为非法内存。
  • pop函数中stacktop = stacktop -1;:free当前节点后,指针减1指向未知内存,无法定位上一个节点。

修复方式:
链表栈的push需将新节点的next指向原栈顶,再更新栈顶为新节点;pop需先保存原栈顶的下一个节点,释放当前栈顶后,将栈顶更新为保存的节点。

2. main函数scanf格式符错误

scanf(" %s", &quit);中,quit是char类型,%s是读取字符串的格式符,会向quit的内存位置写入多个字节(含字符串结束符),导致内存越界,破坏其他变量内存。

修复方式:
改用%c格式符读取单个字符:scanf(" %c", &quit);

修复后的完整代码

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

struct point{
    float x;
    float y;
    float z;
}; typedef struct point POINT;

struct stackPoint{
    POINT myPoint;
    struct stackPoint *next;
}; typedef struct stackPoint STACKPOINT;

static STACKPOINT *stacktop = NULL;

void printStackElement(POINT aPoint){
    printf(" x:%f \t y:%f \t z:%f\n", aPoint.x, aPoint.y, aPoint.z );
}

void push(POINT pushPoint){
    STACKPOINT *newElem = malloc(sizeof(STACKPOINT));
    newElem->next = stacktop;
    newElem->myPoint = pushPoint;
    stacktop = newElem;
}

POINT pop(){
    POINT b = stacktop->myPoint;
    STACKPOINT *temp = stacktop->next;
    free(stacktop);
    stacktop = temp;
    return b;
}

int isEmpty(){
    return stacktop == NULL ? 1 : 0;
}

POINT readPoint(){
    POINT a;
    printf("Please enter your x-Coordinate: ");
    scanf(" %f", &a.x);
    printf("Please enter your y-Coordinate: ");
    scanf(" %f", &a.y);
    printf("Please enter your z-Coordinate: ");
    scanf(" %f", &a.z);
    return a;
}

int main(){
    char quit = 0;
    while(quit != 1 ){
        printf("\n\n enter 'p' to enter another Point or 'q' to quit: ");
        scanf(" %c", &quit);
        switch(quit){
            case 'p':
                push(readPoint());
                break;
            
            case 'q':
                quit = 1;
                break;

            default:
                break;
        }
    }
    while(!isEmpty()){
        printStackElement(pop());
    }
    return 0;
}

验证说明

修复后,程序可正常接收多个点坐标,退出后按栈“后进先出”顺序打印所有点,同时正确释放所有动态分配的内存,无内存错误或无限输出问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 16:55:20