无数道坑中的一道 (记录疑难杂症)

        真的是懵逼了,在学习贪吃蛇的时候,我因为没有注意到这段代码,导致错误而且报错非常离谱,我是个哪里看得出来这样的错误啊,第一次见,反正我直接懵逼了,因为我看了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();  // 添加一个节点
}

详细解释

  1. 保存当前节点

    p = head;

    这一步将当前节点保存到变量 p 中,以便后续释放。

  2. 更新链表头部

     
    head = head->next;

    这一步将 head 指针移动到下一个节点,确保后续操作不会影响当前节点。

  3. 释放当前节点

    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;
}

                                              

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

真的想上岸啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值