Skip to main content

Compilation Flags

The Makefile includes debugging symbols by default:
Makefile:19
CFLAGS       = -Wall -Wextra -Werror -O3 -g -g3

-g

Generates standard debugging information for GDB

-g3

Includes extra debugging information like macro definitions

-O3

Full optimization - may complicate debugging but matches release behavior

-Werror

Treats all warnings as errors - ensures code quality
The combination of -O3 with -g -g3 allows debugging optimized code while maintaining performance. If debugging is difficult due to optimization, temporarily change -O3 to -O0 in the Makefile.

Using GDB

Basic GDB Workflow

1

Compile with debug symbols

make re
The default flags already include -g -g3.
2

Launch GDB

gdb ./cub3d
3

Set breakpoints

(gdb) break main
(gdb) break raycasting.c:102
(gdb) break perform_dda
4

Run with arguments

(gdb) run maps/valid_map.cub
5

Inspect variables

(gdb) print mapa->xx
(gdb) print mapa->ray_dir_x
(gdb) print *mapa

Useful GDB Commands

break raycasting        # Break at function
break drawing.c:52      # Break at specific line
break if i == 866       # Conditional breakpoint (middle of screen)
info breakpoints        # List all breakpoints
delete 1                # Delete breakpoint #1

Debugging Raycasting Issues

Common raycasting bugs and how to debug them:
Likely cause: Incorrect wall distance calculation
(gdb) break calculate_wall_data
(gdb) run maps/map.cub
(gdb) print dist
(gdb) print mapa->line_height
Check that dist is positive and reasonable. The wall height calculation in raycasting.c:76:
raycasting.c:68-82
void	calculate_wall_data(t_map *mapa, double *dist)
{
	if (mapa->side == 0)
		*dist = (mapa->map_x - mapa->xx + (1 - mapa->step_x) / 2)
			/ mapa->ray_dir_x / SIZE;
	else
		*dist = (mapa->map_y - mapa->yy + (1 - mapa->step_y) / 2)
			/ mapa->ray_dir_y / SIZE;
	mapa->line_height = (int)(HEIGHT / *dist);
}
Likely cause: Texture selection logic error
(gdb) break select_texture
(gdb) run maps/map.cub
(gdb) print mapa->side
(gdb) print mapa->ray_dir_x
(gdb) print mapa->ray_dir_y
(gdb) print mapa->current_tex
Verify texture selection in raycasting.c:84-100:
raycasting.c:84-100
void	select_texture(t_map *mapa)
{
	if (mapa->side == 0)
	{
		if (mapa->ray_dir_x > 0)
			mapa->current_tex = &mapa->tex_east;
		else
			mapa->current_tex = &mapa->tex_west;
	}
	else
	{
		if (mapa->ray_dir_y > 0)
			mapa->current_tex = &mapa->tex_south;
		else
			mapa->current_tex = &mapa->tex_north;
	}
}
Likely cause: Collision detection issue in is_wall()
(gdb) break is_wall
(gdb) run maps/map.cub
(gdb) print pos_x
(gdb) print pos_y
(gdb) print mapa->final_map[(int)(pos_y)/SIZE][(int)(pos_x)/SIZE]
Check the collision detection logic in utils6.c:15-27.

Memory Debugging with Valgrind

Basic Valgrind Usage

MLX creates many false positives in Valgrind due to X11 library behavior. Focus on memory you allocate, not MLX internals.
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes ./cub3d maps/valid_map.cub
Flag explanations:
  • --leak-check=full - Show detailed leak information
  • --show-leak-kinds=all - Show all types of leaks
  • --track-origins=yes - Track origin of uninitialized values

Suppressing MLX Leaks

Create a suppression file mlx.supp:
mlx.supp
{
   mlx_leak
   Memcheck:Leak
   ...
   fun:mlx_*
}
{
   x11_leak
   Memcheck:Leak
   ...
   obj:*/libX11.so.*
}
Run with suppressions:
valgrind --leak-check=full --suppressions=mlx.supp ./cub3d maps/map.cub

Common Memory Issues

Check these locations:
  1. Map parsing - ensure freeme() is called on allocated arrays
  2. Texture paths - verify freetextures() in freemem.c:39-49
  3. Map duplication - check final_map and toflood_map cleanup
freemem.c:51-56
void	freeall(t_map *map)
{
	freetextures(map);
	freeme(map->toflood_map);
	freeme(map->final_map);
}
Verify all exit paths call cleanup:
grep -n "exit(" *.c
Ensure freeall() is called before each exit().

Visual Debugging

Drawing Debug Information

Add debug visualization to understand what’s happening:
Debug Helper Example
// In utils7.c or a new debug.c file
void	debug_draw_ray(t_map *mapa, int x, int color)
{
    int y = HEIGHT - 50;  // Bottom of screen
    draw_square(x, y, color, mapa);  // Visualize each ray
}

// In raycasting.c, add to the main loop:
void	raycasting(t_map *mapa, int i)
{
    // ... existing code ...
    while (++i < WIDTH)
    {
        // ... ray calculations ...
        if (hit_wall)
            debug_draw_ray(mapa, i, 0xFF0000);  // Red for wall hit
        else
            debug_draw_ray(mapa, i, 0x00FF00);  // Green for no hit
    }
}
Remove all debug prints before final submission as they violate the norm and slow rendering.
Debug Print Examples
// Player position tracking
printf("Player: (%.2f, %.2f) Angle: %.2f\n", 
    mapa->xx, mapa->yy, mapa->starting_angle);

// Ray information
printf("Ray %d: dir(%.2f, %.2f) hit at (%d, %d)\n",
    i, mapa->ray_dir_x, mapa->ray_dir_y, mapa->map_x, mapa->map_y);

// DDA steps
printf("DDA: side=%d step_x=%d step_y=%d\n",
    mapa->side, mapa->step_x, mapa->step_y);

Performance Profiling

Identify slow functions:
# Compile with profiling
make CFLAGS="-Wall -Wextra -Werror -pg -g"

# Run the program (creates gmon.out)
./cub3d maps/map.cub

# Analyze profile
gprof ./cub3d gmon.out > analysis.txt
less analysis.txt
Look for:
  • Functions called most frequently
  • Functions taking most cumulative time
  • Unexpected call patterns

Common Issues and Solutions

Probable causes:
  1. Invalid map file path
  2. Corrupted .cub file
  3. NULL pointer in t_map structure
Debug approach:
gdb ./cub3d
(gdb) run maps/invalid.cub
(gdb) bt  # Show backtrace
(gdb) frame 0  # Examine crash frame
(gdb) info locals  # Check variable values
Check that init_values() is called before any structure access.
Possible issues:
  1. Textures failed to load
  2. Rendering loop not running
  3. Image not being put to window
Debug steps:
(gdb) break load_texture
(gdb) run maps/map.cub
(gdb) print tex->img_ptr  # Should not be NULL
(gdb) break cubed_render
(gdb) continue  # Check if render loop runs
Verify texture paths in .cub file are correct and files exist.
Likely causes:
  1. Map array out of bounds access
  2. Invalid player position
Debug with watchpoint:
(gdb) watch mapa->xx
(gdb) watch mapa->yy
(gdb) run maps/map.cub
# Move player until crash
(gdb) bt
Check collision detection in is_wall() and movement code in move_cubed().
Meaning: MLX failed to load a texture fileSolutions:
  1. Verify texture file exists: ls -la path/to/texture.xpm
  2. Check file permissions: chmod 644 *.xpm
  3. Validate XPM format - must be valid XPM
  4. Check path in .cub file matches actual file location
The error occurs in main.c:29-41:
main.c:29-41
void	load_texture(t_map *mapa, t_texture *tex, char *path)
{
	tex->img_ptr = mlx_xpm_file_to_image(mapa->mlx_ptr, path,
			&tex->width, &tex->height);
	if (!tex->img_ptr)
	{
		perror("Error cargando textura");
		freeall(mapa);
		exit(1);
	}
Error messages defined in cub3.h:
ErrorCause
ARGERRORWrong number of arguments
ARGERROR2Empty argument
ARGERROR3File doesn’t end with .cub
MAPERROR3Empty map file
MAPERROR4Map not closed (walls)
MAPERROR10Attribute not found
MAP_ARG_DUPDuplicate attribute
SPOTERRORMultiple players or invalid characters
RGBERRORRGB format error
Debug parsing:
(gdb) break parsefloorceilingdirections
(gdb) run maps/map.cub
(gdb) print map->northtexture
(gdb) print map->floorcolor

Error Message Interpretation

All error messages are defined as macros in cub3.h:42-66:
cub3.h:42-66
# define ARGERROR "Debes introducir dos argumentos por terminal\n"
# define ARGERROR2 "Argumento vacio, especifica un mapa\n"
# define ARGERROR3 "El mapa tiene que acabar en .cub\n"
# define MAPERROR "Something went wrong copying the map\n"
# define MAPERROR2 "El mapa no se ha podido abrir\n"
# define MAPERROR3 "Error: Empty map\n"
# define MAPERROR4 "Map is not closed\n"
# define MAPERROR5 "North word is wrong\n"
# define MAPERROR6 "South word is wrong\n"
# define MAPERROR7 "West word is wrong\n"
# define MAPERROR8 "East word is wrong\n"
# define MAPERROR9 "Something went wrong checking atributes\n"
# define MAPERROR10 "Atribute not found\n"
# define MAP_ARG_DUP "Atribute is found more than once "
# define IMG "The image of one of the directions was not found in the system\n"
# define FORMAT "Tiene que tener nombre y extension .cub\n"
# define FORMAT2 "El nombre del mapa deberia ser printable\n"
# define FORMAT3 "There is some non digit character\n"
# define SPOTERROR "Should have only one player and map with only 0 and 1\n"
# define MEMERROR "Memory allocation failed\n"
# define RGBERROR "There aren't three arguments after spliting\n"
# define RGBERROR2 "Some introduced number is not valid for rgb standard\n"
# define FLOOR "Floor character wrong\n"
# define CEILING "Ceiling character wrong\n"
# define NOPATH "No path to file to open\n"
Use grep to find where each error is triggered:
grep -n "MAPERROR4" *.c

Debugging Checklist

1

Reproduce the bug

Can you consistently trigger the issue?
2

Identify the module

Is it parsing, rendering, movement, or memory-related?
3

Add breakpoints

Set GDB breakpoints in the suspected module
4

Inspect state

Check variable values at each step
5

Trace execution

Use next and step to follow code flow
6

Check memory

Run Valgrind if you suspect memory corruption
7

Fix and verify

Make the fix and test thoroughly
8

Test edge cases

Ensure fix doesn’t break other functionality