真的是懵逼了,在学习贪吃蛇的时候,我因为没有注意到这段代码,导致错误而且报错非常离谱,我是个哪里看得出来这样的错误啊,第一次见,反正我直接懵逼了,因为我看了10边正确的代码和我的现在的代码是一样的啊,后面才发现了问题出现在这 什么问题呢?
总的来说就是链表结构被损坏 输出后就是这样的,因为我有一段代码真的没有注意到
错误显示这样
是在 initSnake()
函数中释放链表时的逻辑错误。让我们详细分析一下问题的根源和修复方法。
问题分析
在 initSnake()
函数中,最初写的代码是:
while (head != NULL) {
p = head;
p = p->next; // 这里有问题
free(p); // 这里有问题
}
问题 1:free(p)
释放了错误的节点
-
在
p = p->next;
之后,p
指向了下一个节点。 -
然后
free(p);
释放了下一个节点,而不是当前节点。 -
这导致当前节点没有被释放,而下一个节点被释放了,从而导致内存泄漏。
问题 2:head
没有正确更新
-
由于
head
没有正确更新,链表的头部仍然指向一个已经被释放的节点(或未释放的节点),这会导致后续操作(如访问链表)时出现未定义行为,甚至程序崩溃。
修复方法
正确的释放链表逻辑应该是:
while (head != NULL) {
p = head; // 保存当前节点
head = head->next; // 更新 head 指向下一个节点
free(p); // 释放当前节点
}
修复后的 initSnake()
函数
void initSnake() {
struct Snake *p;
while (head != NULL) {
p = head; // 保存当前节点
head = head->next; // 更新 head 指向下一个节点
free(p); // 释放当前节点
}
head = (struct Snake *)malloc(sizeof(struct Snake));
head->hang = 2;
head->lie = 2;
head->next = NULL;
tail = head;
addNode(); // 添加一个节点
}
详细解释
-
保存当前节点:
p = head;
这一步将当前节点保存到变量
p
中,以便后续释放。 -
更新链表头部:
head = head->next;
这一步将
head
指针移动到下一个节点,确保后续操作不会影响当前节点。 -
释放当前节点:
free(p);
这一步释放当前节点,避免内存泄漏。
为什么之前的代码会报错
在之前的代码中:
p = head;
p = p->next; // 这里有问题
free(p); // 这里有问题
-
p = p->next;
使得p
指向了下一个节点。 -
然后
free(p);
释放了下一个节点,而不是当前节点。 -
这导致当前节点没有被释放,而下一个节点被释放了。
-
如果链表只有一个节点,
p = p->next;
会使得p
变为NULL
,然后free(p);
会尝试释放NULL
,这本身不会报错,但会导致逻辑混乱。 -
如果链表有多个节点,
free(p);
会释放错误的节点,导致链表结构损坏。
总结
修复后的代码确保了链表的每个节点都被正确释放,同时避免了对未定义内存的访问。希望这个解释清楚地说明了问题的原因和修复方法。
当时的全部代码(正确版)
#include <curses.h>
#include <stdlib.h>
struct Snake
{
int hang;
int lie;
struct Snake *next;
};
struct Snake *head = NULL;
struct Snake *tail = NULL;
void initNcurse()
{
initscr();
keypad(stdscr,1);
noecho();
}
int ifSnakeNode(int i,int j)
{
struct Snake *p;
p = head;
while(p!=NULL){
if(p->hang == i && p->lie == j){
return 1;
}
p= p->next;
}
return 0;
}
void addNode()
{
struct Snake *new;
new=(struct Snake *)malloc(sizeof(struct Snake));
new->hang=tail->hang;
new->lie=tail->lie+1;
tail->next=new;
new->next=NULL;
tail=new;
}
void initSnake()
{
struct Snake *p;
while(head !=NULL){
p=head;
head=head->next;
free(p);
}
head=(struct Snake *)malloc(sizeof(struct Snake));
head->hang=2;
head->lie=2;
head->next=NULL;
tail=head;
addNode();
}
void deleteNode()
{
struct Snake *p;
p=head;
head=head->next;
free(p);
}
void moveSnake()
{
addNode();
if(tail->hang == 20 || tail->hang == 0 ||tail->lie == 0 || tail->lie == 20){
initSnake();
}
deleteNode();
}
void gamepic()
{
int hang;
int lie;
move(0,0);
for(hang=0;hang<20;hang++){
if(hang==0){
for(lie=0;lie<20;lie++){
printw("--");
}
printw("\n");
for(lie=0;lie<=20;lie++){
if(lie==0 || lie==20){
printw("|");
}else{
printw(" ");
}
}
printw("\n");
}
if(hang>0 && hang<=19){
for(lie=0;lie<=20;lie++){
if(lie==0 || lie==20){
printw("|");
}else if(ifSnakeNode(hang,lie)){
printw("[]");
}else{
printw(" ");
}
}
printw("\n");
}
if(hang==19){
for(lie=0;lie<20;lie++){
printw("--");
}
printw("\n");
printw("by shijintao");
}
}
}
int main()
{
int con;
initNcurse();
initSnake();
gamepic();
while(1){
con = getch();
if(con = KEY_RIGHT){
moveSnake();
gamepic();
}
}
getch();
endwin();
return 0;
}