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

基于Raycasting的Doom类3D引擎链表墙体指针异常求助

问题描述

我正在使用raycasting开发一款Doom类3D引擎,链表在int字段测试中可正常工作,但问题似乎出在calculate_wall_projection函数生成的wall指针及通过append_to_list存入链表的过程中。

当我在渲染循环的第二个循环中打印current->object内容时,多数条目显示wall 960,最后39个条目显示本应是最后一条的999;遍历链表前打印head和head->next,也显示960相关数据。由于后续要添加精灵,我需使用链表这种动态数据结构,现求助解决该指针异常问题。

相关代码

typedef struct s_list
{
    t_object    *object;
    struct s_list   *next;
}           t_list;

int rendering_game(t_screen *screen)
{
    t_list      *head;
    t_list      *current;
    t_object    *wall;
    t_ray       ray;

    ray.nbr = 0;
    handle_movement(screen);
    head = NULL;
    while (ray.nbr < screen->scene.resolution.width)
    {
        init_ray(&ray, screen);
        wall = calculate_wall_projection(screen, &ray);
        append_to_list(wall, &head);
        ray.nbr += RAY_INCREMENT;
    }
    current = head;
    while (current != NULL)
    {
        object = current->object;
        draw_texture_line(screen, object);
        current = current->next;
    }
    check_time(screen);
    swap_frame_screen(screen);
    destroy_list(head);
    return (0);
}

t_object    *calculate_wall_projection(t_screen *screen, t_ray *ray)
{
    t_object    *wall;

    wall = (t_object *) malloc(sizeof(t_object));
    get_dist_to_vertical_wall(screen->scene.map, ray);
    get_dist_to_horizontal_wall(screen->scene.map, ray);
    wall = get_shorter_distance(&ray->vertical_check, &ray->horizontal_check);
    correct_fishbowl_effect(screen, wall);
    calculate_projection(screen, wall);
    wall->ray_nbr = ray->nbr;
    define_buffer_coordinate(screen, wall);
    return (wall);
}

void    append_to_list(t_object *obj, t_list **head)
{
    t_list  *new_node;
    t_list  *current;

    new_node= (t_list*) malloc(sizeof(t_list));
    new_node->object = obj;
    new_node->next = NULL;
    current = *head;
    if (*head == NULL)
    {
        *head = new_node;
        return ;
    }
    while (current->next != NULL)
        current = current->next;
    current->next = new_node;
}
问题分析与解决方案

核心问题

你的calculate_wall_projection函数存在内存泄漏+指针覆盖的严重问题:

  • 首先用malloc分配了一个t_object给wall,但紧接着就把wall重新赋值为get_shorter_distance的返回值——直接导致之前malloc的内存丢失,同时链表中所有节点的object指针,大概率都指向了同一个(或少数几个)重复的内存地址。
  • 推测get_shorter_distance函数返回的不是新分配的内存,而是指向ray->vertical_check或ray->horizontal_check中的某个内部结构体指针——而ray是rendering_game函数中的局部变量,每次循环都会被重新初始化,或者这两个check结构体是复用的,导致所有链表节点的object都指向同一个内存区域,最后一次循环的数据会覆盖之前的所有内容,就出现了多数条目显示最后几次循环数据的情况。

修复步骤

1. 修正calculate_wall_projection的内存逻辑

不要直接覆盖malloc出来的wall指针,而是把get_shorter_distance返回的数据拷贝到你分配的wall内存中,而非赋值指针:

t_object    *calculate_wall_projection(t_screen *screen, t_ray *ray)
{
    t_object    *wall;
    t_object    *shorter_wall;

    wall = (t_object *) malloc(sizeof(t_object));
    if (!wall) { /* 添加内存分配失败的判断,避免空指针操作 */
        return NULL;
    }
    get_dist_to_vertical_wall(screen->scene.map, ray);
    get_dist_to_horizontal_wall(screen->scene.map, ray);
    shorter_wall = get_shorter_distance(&ray->vertical_check, &ray->horizontal_check);
    /* 把shorter_wall的数据拷贝到我们自己分配的wall内存里 */
    *wall = *shorter_wall;
    correct_fishbowl_effect(screen, wall);
    calculate_projection(screen, wall);
    wall->ray_nbr = ray->nbr;
    define_buffer_coordinate(screen, wall);
    return (wall);
}

2. 检查get_shorter_distance的返回值

确认这个函数返回的是t_object类型的指针,并且指向的是ray->vertical_check或ray->horizontal_check的结构体本身(而非动态分配的内存)——如果是动态分配的,还需要处理对应的内存释放逻辑,避免泄漏。

3. 完善内存释放逻辑

确保destroy_list函数不仅释放链表节点的内存,还要释放每个节点中object指针指向的t_object内存,否则会造成内存泄漏:

void destroy_list(t_list *head) {
    t_list *temp;
    while (head != NULL) {
        temp = head;
        head = head->next;
        free(temp->object); /* 释放每个t_object实例 */
        free(temp); /* 释放链表节点 */
    }
}

4. 修复渲染循环中的变量未声明问题

rendering_game函数的第二个循环里,object变量没有声明,需要补充声明:

current = head;
while (current != NULL)
{
    t_object *object = current->object;
    draw_texture_line(screen, object);
    current = current->next;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 11:45:42