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
相关产品推荐
相关产品推荐

