From 0070779007cd9bb782de41d0b40cfb0034de1ddf Mon Sep 17 00:00:00 2001 From: Ulysse Cura Date: Tue, 1 Sep 2026 17:29:31 +0200 Subject: [PATCH] Even better error handling with goto. --- src/asset_manager.c | 38 +++++++++++++++++-------------------- src/display.c | 1 + src/headers/asset_manager.h | 3 ++- src/headers/errors.h | 7 +++++++ src/main.c | 18 +++++++++++------- src/texture.c | 17 ++++++++--------- 6 files changed, 46 insertions(+), 38 deletions(-) diff --git a/src/asset_manager.c b/src/asset_manager.c index ff74295..b6e0083 100644 --- a/src/asset_manager.c +++ b/src/asset_manager.c @@ -12,17 +12,8 @@ // Args : asset_type_t asset_type, const char *asset_name int create_asset(asset_t *asset, va_list args) { - asset->type = va_arg(args, asset_type_t); - - const char *asset_name = va_arg(args, const char *); - asset->name = calloc(strlen(asset_name) + 1, sizeof(char)); - if(!asset->name) - { - error_printf("Failed to allocate memory for asset name : %d", errno); - return EXIT_FAILURE; - } - strcpy(asset->name, asset_name); - + asset->name = va_arg(args, const char *); + asset->type = ASSET_NULL; asset->nb_refs = 0; return EXIT_SUCCESS; @@ -30,8 +21,6 @@ int create_asset(asset_t *asset, va_list args) int destroy_asset(asset_t *asset) { - free(asset->name); - switch(asset->type) { case ASSET_TEXTURE: @@ -42,6 +31,9 @@ int destroy_asset(asset_t *asset) if(destroy_map(asset->data)) return_failure_int; break; + case ASSET_NULL: + break; + default: error_printf("Asset type not valid : %d", asset->type); return EXIT_FAILURE; @@ -154,9 +146,10 @@ asset_t *asset_manager_load_asset(char *asset_name, asset_type_t asset_type) elem_t *asset_elem = linked_list_get_if(&game.asset_manager.assets, condition_is_asset_name, (void *)asset_name); if(asset_elem) { - ((asset_t *)asset_elem->data)->nb_refs++; + asset_t *asset = asset_elem->data; + asset->nb_refs++; - debug_printf("Asset \"%s\" has already been loaded, nb refs : %d", ((asset_t *)asset_elem->data)->name, ((asset_t *)asset_elem->data)->nb_refs); + debug_printf("Asset \"%s\" has already been loaded, nb refs : %d", asset->name, asset->nb_refs); } else { @@ -169,7 +162,7 @@ asset_t *asset_manager_load_asset(char *asset_name, asset_type_t asset_type) } asset_header_def_t *asset_header_def = asset_header_def_elem->data; - asset_elem = create_elem(&game.asset_manager.assets, asset_type, asset_name); + asset_elem = create_elem(&game.asset_manager.assets, asset_name); if(!asset_elem) return_failure_ptr; asset_t *asset = asset_elem->data; @@ -183,20 +176,24 @@ asset_t *asset_manager_load_asset(char *asset_name, asset_type_t asset_type) { case ASSET_TEXTURE: asset->data = load_texture(); - if(!asset->data) return_failure_ptr; break; case ASSET_MAP: asset->data = load_map(); - if(!asset->data) return_failure_ptr; break; default: error_printf("Asset type doesn't exists : %d", asset_type); - destroy_asset(asset); - return NULL; + break; } + if(!asset->data) + { + destroy_elem(&game.asset_manager.assets, asset_elem); // returns failure anyway + return_failure_ptr; + } + + asset->type = asset_type; asset->nb_refs++; linked_list_push_back(&game.asset_manager.assets, asset_elem); @@ -217,7 +214,6 @@ int asset_manager_let_go_asset(char *asset_name) } asset_t *asset = asset_elem->data; - asset->nb_refs--; debug_printf("Asset \"%s\" has been let go, nb refs : %d", asset->name, asset->nb_refs); diff --git a/src/display.c b/src/display.c index 11f66d5..433de1c 100644 --- a/src/display.c +++ b/src/display.c @@ -61,6 +61,7 @@ inline int display_init(void) } debug_printf("Initialized display."); + return EXIT_SUCCESS; } diff --git a/src/headers/asset_manager.h b/src/headers/asset_manager.h index e12688a..385900a 100644 --- a/src/headers/asset_manager.h +++ b/src/headers/asset_manager.h @@ -6,12 +6,13 @@ #include "linked_list.h" typedef enum asset_type_t { + ASSET_NULL, ASSET_TEXTURE, ASSET_MAP } asset_type_t; typedef struct asset_t { - char *name; + const char *name; void *data; diff --git a/src/headers/errors.h b/src/headers/errors.h index 0e68cc6..9b5805b 100644 --- a/src/headers/errors.h +++ b/src/headers/errors.h @@ -27,11 +27,18 @@ fprintf(stderr, "\tin %s:%d:%s()\n", __FILE__, __LINE__, __func__); \ return NULL; \ } while (0); +#define goto_failure \ + do { \ + fprintf(stderr, "\tin %s:%d:%s()\n", __FILE__, __LINE__, __func__); \ + goto failure; \ + } while (0); + #else #define debug_printf(...) #define return_failure_int return EXIT_FAILURE; #define return_failure_ptr return NULL; +#define goto_failure goto failure; #endif #define warning_printf(...) \ diff --git a/src/main.c b/src/main.c index bc463fa..09cb5b6 100644 --- a/src/main.c +++ b/src/main.c @@ -2,6 +2,7 @@ #include #include +#include "errors.h" game_t game; @@ -16,19 +17,22 @@ static inline void update_time(void) int main(void) { - int exit_status = EXIT_SUCCESS; - - if(game_init()) exit_status = EXIT_FAILURE; + if(game_init()) goto_failure; while(game.is_running) { update_time(); game_handle_event(); - if(game_update()) exit_status = EXIT_FAILURE; - if(game_render()) exit_status = EXIT_FAILURE; + if(game_update()) goto_failure; + if(game_render()) goto_failure; } - if(game_exit()) exit_status = EXIT_FAILURE; + if(game_exit()) return_failure_int; - return exit_status; + return EXIT_SUCCESS; + +failure: + game_exit(); // return failure anyway + + return EXIT_FAILURE; } diff --git a/src/texture.c b/src/texture.c index b633830..b159a19 100644 --- a/src/texture.c +++ b/src/texture.c @@ -31,35 +31,34 @@ texture_t *load_texture(void) if(!SDL_LockSurface(tmp_surface)) { error_printf("Failed to lock temporary surface : %s", SDL_GetError()); - SDL_DestroySurface(tmp_surface); - return NULL; + goto_failure; } if(fread(tmp_surface->pixels, sizeof(uint16_t), width * height, game.asset_manager.asset_file) != (size_t)width * (size_t)height) { error_printf("Failed to read asset file."); - SDL_DestroySurface(tmp_surface); - return NULL; + goto_failure; } if(!SDL_SetSurfaceColorKey(tmp_surface, true, TEXTURE_TRANSPARENT_COLOR)) { error_printf("Failed to set color key of temporary surface : %s", SDL_GetError()); - SDL_DestroySurface(tmp_surface); - return NULL; + goto_failure; } texture_t *texture = SDL_CreateTextureFromSurface(game.display.renderer, tmp_surface); if(!texture) { error_printf("Failed to create texture from temporary surface : %s", SDL_GetError()); - SDL_DestroySurface(tmp_surface); - return NULL; + goto_failure; } SDL_DestroySurface(tmp_surface); - return texture; + +failure: + SDL_DestroySurface(tmp_surface); + return NULL; } void destroy_texture(texture_t *texture)