AiSiBi77 2019-07-09 13:08 采纳率: 0%
浏览 514

c语言 free() 需要释放分配结构里面分配的结构内存么-贪吃蛇-链表

结构如下
这样分配了内存
释放链表

这需要释放node中 position 分配的内存么(注释地方);
我 如果释放position 就会报错
有大佬知道么

更新;->
出链表的时候释放没报错
图片说明


图片说明


当最后程序结束是清空释放 position 报错
图片说明


图片说明


图片说明


图片说明

我认为position位置应该是有效的,程序其他地方也没去变动position地址

代码片段(代码主要是github大佬的代码,https://github.com/mnisjk/snake.git)

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <curses.h>
#include <sys/select.h>
#include <time.h>

#define SRC_WIDTH 70
#define SRC_HEIGHT 20

WINDOW *g_mainwin;
int g_oldcur, g_score = 0, g_width, g_height;

typedef struct
{
    int x;
    int y;
} pos;

pos fruit;

bool *spaces;


// queue stuff
struct s_node
{
    pos *position;
    struct s_node *prev;
    struct s_node *next;
} *front = NULL,*back =NULL;

typedef struct s_node node;

pos * peek(){
    return front == NULL ? NULL : front->position;
}

node * dequeue(){
    node *oldfront = front;
    front = front->next;
    return oldfront;
}

//queue a position at the back
void enqueue(pos position)
{
    pos *newpos = (pos *)malloc(sizeof(position));
    node *newnode = (node *)malloc(sizeof(node));

    newpos->x = position.x;
    newpos->y = position.y;
    newnode->position = newpos;
    if(front == NULL && back ==NULL)
        front = back = newnode;
    else
    {
        back->next = newnode;
        newnode->prev = back;
        back = newnode;
    }
}

//end queue stuff

//start snake stuff
void snake_write_text(int y,int x,char *str)
{
    mvwaddstr(g_mainwin, y, x, str);
}

//draw the borders
void snake_draw_board()
{
    int i;
    for (i = 0; i < g_height;i++){
        snake_write_text(i, 0, "|");
        snake_write_text(i, g_width - 1, "|");
    }
    for (i = 0; i < g_width;i++)
    {
        snake_write_text(0, i, "-");
        snake_write_text(g_height, i, "-");
    }
    snake_write_text(g_height + 1, 2, "Score:");
}

//resets the terminal window and clears up the mem
void snake_game_over(int i,pos p)
{
    free(spaces);
    while (front)
    {
        node *n = front;
        front = front->next;
        free(n->position);
        free(n);
    }

    endwin();
    printf("%d\n", i);
    printf("%d,%d\n",p.x,p.y);
    exit(0);
}

//当前位置是否在界限里面
bool snake_in_bounds(pos position)
{
    return position.y < g_height && position.y > 0 && position.x < g_width - 1 && position.x > 0;
}

//2d坐标映射1d
int snake_cooridinate_to_index(pos position)
{
    return g_width * position.y + position.x;
}

//1d映射对应的坐标
pos snake_index_to_coordinate(int index)
{
    int x = index % g_width;
    int y = index / g_width;
    return (pos){x, y};
}

//随机出现水果
void snake_draw_fruit()
{
    attrset(COLOR_PAIR(3));
    int idx;
    do{
        idx = rand() % (g_width * g_height);
        fruit = snake_index_to_coordinate(idx);
    } while (spaces[idx] || !snake_in_bounds(fruit));
    attron(A_REVERSE);
    snake_write_text(fruit.y, fruit.x, " ");
    attroff(A_REVERSE);
}

//handles moving the snake for each iteration
bool snake_move_player(pos head)
{
    attrset(COLOR_PAIR(1));

    //check if we ran into ourself
    int idx = snake_cooridinate_to_index(head);
    if(spaces[idx]){
        pos te = {2, 2};
        snake_game_over(2,te);
    }

    spaces[idx] = true;
    enqueue(head);

    //check if we're eating the fruit
    if(head.x == fruit.x && head.y == fruit.y)
    {
        snake_draw_fruit();
        g_score += 10;
    }else{

        node *tail = dequeue();
        pos tem = *(tail->position);
        spaces[snake_cooridinate_to_index(tem)] = false;

        snake_write_text(tem.y, tem.x, " ");
        //if(tail->position != NULL)
        free(tail->position);
        free(tail);
        tail = NULL;
    }
    attron(A_REVERSE);
    snake_write_text(head.y, head.x, " ");
    attroff(A_REVERSE);

    char buffer[25];
    sprintf(buffer, "%d", g_score);
    attrset(COLOR_PAIR(2));
    snake_write_text(g_height+1,9,buffer);
}

void check_move_pos(pos *t_head,pos *head){
    pos temp;
    node t_node = *back;
    if (&t_node == NULL)
        return ;
    else
    {   

        if(t_node.prev != NULL){
            if((t_node.prev)->position != NULL){
                temp = *((t_node.prev)->position);
                if(t_head->x == head->x){ //x方向
                    if(temp.x == head->x && temp.y == head->y){
                        if(t_head->y > temp.y)
                            head->y += 2;
                        else
                            head->y -= 2;
                    }
                }else if(t_head->y == head->y) { //y方向
                    if(temp.x == head->x && temp.y == head->y){
                        if(t_head->x > temp.x)
                            head->x += 2;
                        else
                            head->x -= 2;
                    }
                }  
                }

        }
    }
}

int main(int argc,char *argv[])
{
    int key = KEY_RIGHT;
    if((g_mainwin = initscr()) == NULL)
    {
        perror("error initialising ncursess");
        exit(EXIT_FAILURE);
    }

    srand(time(NULL));
    noecho();
    curs_set(2);
    halfdelay(1);
    keypad(g_mainwin, TRUE);
    g_oldcur = curs_set(0);

    start_color( );
    init_pair( 1, COLOR_RED,     COLOR_BLACK );
    init_pair( 2, COLOR_GREEN,   COLOR_BLACK );
    init_pair( 3, COLOR_YELLOW,  COLOR_BLACK );
    init_pair( 4, COLOR_BLUE,    COLOR_BLACK );
    init_pair( 5, COLOR_CYAN,    COLOR_BLACK );
    init_pair( 6, COLOR_MAGENTA, COLOR_BLACK );
    init_pair( 7, COLOR_WHITE,   COLOR_BLACK );
    getmaxyx( g_mainwin, g_height, g_width );

    g_width  = g_width  < SRC_WIDTH  ? g_width  : SRC_WIDTH;
    g_height = g_height < SRC_HEIGHT ? g_height : SRC_HEIGHT; 

    // Set up the 2D array of all spaces
    spaces = (bool*) malloc( sizeof( bool ) * g_height * g_width );

    snake_draw_board( );
    snake_draw_fruit( );
    pos head = { 5,5 };
    enqueue( head );

    // Event loop
    while( 1 )
    {
        pos t_head = head;
        int in = getch();
        if( in != ERR )
            key = in;
        switch (key)
        {
            case KEY_DOWN:
            case 'k':
            case 'K':
                head.y++;
                break;
            case KEY_RIGHT:
            case 'l':
            case 'L':
                head.x++;
                break;
            case KEY_UP:
            case 'j':
            case 'J':
                head.y--;
                break;
            case KEY_LEFT:
            case 'h':
            case 'H':
                head.x--;
                break;
            }
            //禁止反向
            check_move_pos(&t_head, &head);
            if (!snake_in_bounds(head))
                snake_game_over(3, head);
            else
                snake_move_player(head);


    }
    pos te = {4, 4};
    snake_game_over(4,te);
}

调试了 越来混乱了,一运行蛇啥不吃,链表里面应该只有一个地址才对,出链表也对应的释放了地址.可调试出现了最后出现了3个

图片说明

更新->

搞好了,
图片说明

新建节点 node *newnode = (node *)malloc(sizeof(node));时候,莫名
newnode 中 next 指针指向了未知 地址,按原本意思应该指向 0x0空地址

所有 newnode->next = newnode->prev = NULL; 初始化一下,不然结束的释放链表 就会找到这个 0x20 的地址

图片说明


图片说明

一切正常了 ,高兴

  • 写回答

3条回答 默认 最新

  • threenewbee 2019-07-09 17:58
    关注

    因为你 newnode->position = newpos;
    而newpos又是malloc动态分配的
    所以需要free
    只要你有malloc,就需要free

    如果你没有malloc
    newnode->position = &某个栈上的结构体变量;
    这样就不需要,也不能释放。

    评论

报告相同问题?

悬赏问题

  • ¥15 seatunnel-web使用SQL组件时候后台报错,无法找到表格
  • ¥15 fpga自动售货机数码管(相关搜索:数字时钟)
  • ¥15 用前端向数据库插入数据,通过debug发现数据能走到后端,但是放行之后就会提示错误
  • ¥30 3天&7天&&15天&销量如何统计同一行
  • ¥30 帮我写一段可以读取LD2450数据并计算距离的Arduino代码
  • ¥15 飞机曲面部件如机翼,壁板等具体的孔位模型
  • ¥15 vs2019中数据导出问题
  • ¥20 云服务Linux系统TCP-MSS值修改?
  • ¥20 关于#单片机#的问题:项目:使用模拟iic与ov2640通讯环境:F407问题:读取的ID号总是0xff,自己调了调发现在读从机数据时,SDA线上并未有信号变化(语言-c语言)
  • ¥20 怎么在stm32门禁成品上增加查询记录功能