Memory cleanup in this project is built around a simple rule: long-lived runtime
resources are owned by t_app, and the final release gate is free_app(...).
Temporary parser and validation allocations stay outside that ownership tree.
Ownership and teardown
`t_app` is the ownership root, `free_app(...)` is the release gate
Cleanup is correct here because ownership is centralized. Runtime resources live under
`t_app`, temporary parser/validation buffers stay local, and teardown follows a strict order
for MLX and heap resources.
config strings `tex_no/so/we/ea` and parsed path ownership
map.grid final validated map storage owned by runtime
MLX handles `mlx_ptr` and `win_ptr` created during graphics init
images / textures frame image and mandatory texture images
bonus state bonus-owned arrays, images, and subsystem contexts
1 free config texture paths config strings
if ptr 2 destroy mandatory textures MLX images
if img_ptr 3 bonus shutdown helpers minimap, walls, retro, doors, HUD, pickups, sprites
delegated 4 destroy frame image frame buffer
if img_ptr 5 destroy window MLX window
if win_ptr 6 destroy display MLX display
if mlx_ptr BFS context
`visited`, queues, and validation-local buffers are released by
`finish_validation(...)`.
parser lines[]
temporary `char **lines` storage is released inside the parsing flow on success and
error paths.
valgrind --leak-check=full \
--track-fds=yes \
--show-leak-kinds=all \
./cub3D maps/valid.cub
./cub3D maps/invalid.cub
./cub3D maps/no_spawn.cub
./cub3D maps/open_wall.cub
no definite project leaks no project-owned FD leak same result on error paths
The project uses t_app as the primary ownership root.
That includes:
- parsed texture path strings
- final map grid storage
- MLX display and window handles
- frame image and mandatory texture images
- bonus-owned subsystem memory and images
Because ownership is centralized, shutdown stays understandable and consistent.
The teardown order matters, especially for graphics resources:
- free config strings
- destroy mandatory texture images
- destroy bonus and retro image resources through their shutdown helpers
- destroy window
- destroy display
- free MLX context
- free map storage
The implementation interleaves some image destroys with bonus shutdown helpers,
but all MLX images are released before the display context is destroyed.
Not every allocation belongs to t_app.
Two important temporary groups stay local:
- BFS validation resources (
visited, queues, local validation buffers)
- parser line arrays and intermediate text storage
These are released inside their own stage and never escape into the global app lifetime.
Any startup failure after ownership begins routes back to cleanup in main.
Typical covered cases:
- invalid map or parser failure
- texture load failure
- MLX init or image creation failure
- bonus subsystem init failure
The expected result is always the same: no partially owned state is left allocated.
Resource hygiene is checked with:
valgrind --leak-check=full --track-fds=yes
- repeated open/close tests
- invalid input startup tests
- parser failure cases
That verifies both normal shutdown and failure-path cleanup.
srcs/core/shutdown.c
srcs/tools/utils.c
srcs/core/main.c
srcs/validation/validate_closed_setup.c
srcs/validation/validate_bfs.c