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

