From 13f8f2b66b624268666ee868e8c1ca88e729f4d9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Mar 2023 17:04:52 +0900 Subject: [PATCH] [util] Fix a pile of memory leaks Some were actually legitimate (in that they'd cause problems in a long running game). --- libs/util/idparse.c | 15 +++++++ libs/util/qargs.c | 13 ++++++ libs/util/quakefs.c | 94 +++++++++++++++++++++++---------------- libs/util/segtext.c | 13 ++++++ libs/util/set.c | 13 ++++++ libs/util/sys.c | 58 +++++++++++++++++------- libs/util/test/test-seg.c | 3 ++ libs/util/va.c | 24 ++++++++-- 8 files changed, 175 insertions(+), 58 deletions(-) diff --git a/libs/util/idparse.c b/libs/util/idparse.c index 440f74029..24aac7c3f 100644 --- a/libs/util/idparse.c +++ b/libs/util/idparse.c @@ -40,6 +40,7 @@ #include "QF/cbuf.h" #include "QF/cmd.h" #include "QF/idparse.h" +#include "QF/sys.h" typedef struct idbuf_s { dstring_t *buf, *line; @@ -253,3 +254,17 @@ VISIBLE cbuf_interpreter_t id_interp = { COM_execute_sets, NULL }; + +static void +idparse_shutdown (void *data) +{ + if (_com_token) { + dstring_delete (_com_token); + } +} + +static void __attribute__((constructor)) +idparse_init (void) +{ + Sys_RegisterShutdown (idparse_shutdown, 0); +} diff --git a/libs/util/qargs.c b/libs/util/qargs.c index ad7eda0e7..d2103ab22 100644 --- a/libs/util/qargs.c +++ b/libs/util/qargs.c @@ -242,3 +242,16 @@ COM_ExecConfig (cbuf_t *cbuf, int skip_quakerc) } } } + +static void +qargs_shutdown (void *data) +{ + free (largv); + free ((char *) com_cmdline); +} + +static void __attribute__((constructor)) +qargs_init (void) +{ + Sys_RegisterShutdown (qargs_shutdown, 0); +} diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index 530fcb03b..bc3b511fa 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -571,6 +571,42 @@ qfs_process_path (const char *path, const char *gamedir) } } +static void +qfs_free_gamedir (void) +{ + if (qfs_gamedir) { + if (qfs_gamedir->name) + free ((char *)qfs_gamedir->name); + if (qfs_gamedir->gamedir) + free ((char *)qfs_gamedir->gamedir); + if (qfs_gamedir->path) + free ((char *)qfs_gamedir->path); + if (qfs_gamedir->gamecode) + free ((char *)qfs_gamedir->gamecode); + if (qfs_gamedir->hudtype) + free ((char *)qfs_gamedir->hudtype); + if (qfs_gamedir->dir.def) + free ((char *)qfs_gamedir->dir.def); + if (qfs_gamedir->dir.skins) + free ((char *)qfs_gamedir->dir.skins); + if (qfs_gamedir->dir.models) + free ((char *)qfs_gamedir->dir.models); + if (qfs_gamedir->dir.sound) + free ((char *)qfs_gamedir->dir.sound); + if (qfs_gamedir->dir.maps) + free ((char *)qfs_gamedir->dir.maps); + if (qfs_gamedir->dir.shots) + free ((char *)qfs_gamedir->dir.shots); + free (qfs_gamedir); + } + + while (qfs_vpaths) { + vpath_t *next = qfs_vpaths->next; + delete_vpath (qfs_vpaths); + qfs_vpaths = next; + } +} + static void qfs_build_gamedir (const char **list) { @@ -584,33 +620,7 @@ qfs_build_gamedir (const char **list) qfs_set_var (vars, "game", qfs_game); - if (qfs_gamedir) { - if (qfs_gamedir->name) - free ((char *)qfs_gamedir->name); - if (qfs_gamedir->gamedir) - free ((char *)qfs_gamedir->gamedir); - if (qfs_gamedir->path) - free ((char *)qfs_gamedir->path); - if (qfs_gamedir->gamecode) - free ((char *)qfs_gamedir->gamecode); - if (qfs_gamedir->dir.def) - free ((char *)qfs_gamedir->dir.def); - if (qfs_gamedir->dir.skins) - free ((char *)qfs_gamedir->dir.skins); - if (qfs_gamedir->dir.models) - free ((char *)qfs_gamedir->dir.models); - if (qfs_gamedir->dir.sound) - free ((char *)qfs_gamedir->dir.sound); - if (qfs_gamedir->dir.maps) - free ((char *)qfs_gamedir->dir.maps); - free (qfs_gamedir); - } - - while (qfs_vpaths) { - vpath_t *next = qfs_vpaths->next; - delete_vpath (qfs_vpaths); - qfs_vpaths = next; - } + qfs_free_gamedir (); for (j = 0; list[j]; j++) ; @@ -829,13 +839,10 @@ QFS_WriteFile (const char *filename, const void *data, int len) Qclose (f); } -static int_findfile_t * -qfs_findfile_search (const vpath_t *vpath, const searchpath_t *sp, - const char **fnames) +static int_findfile_t found; +static void +clear_findfile (void) { - static int_findfile_t found; - const char **fn; - found.ff.vpath = 0; found.ff.in_pak = false; found.pack = 0; @@ -849,6 +856,15 @@ qfs_findfile_search (const vpath_t *vpath, const searchpath_t *sp, free ((char *) found.path); found.path = 0; } +} + +static int_findfile_t * +qfs_findfile_search (const vpath_t *vpath, const searchpath_t *sp, + const char **fnames) +{ + const char **fn; + + clear_findfile (); // is the element a pak file? if (sp->pack) { dpackfile_t *packfile = 0; @@ -1456,11 +1472,13 @@ qfs_path_cvar (void *data, const cvar_t *cvar) static void qfs_shutdown (void *data) { - while (qfs_vpaths) { - vpath_t *next = qfs_vpaths->next; - delete_vpath (qfs_vpaths); - qfs_vpaths = next; - } + clear_findfile (); + qfs_free_gamedir (); + PL_Free (qfs_gd_plist); + free ((char *) qfs_userpath); + free (gamedir_callbacks); + ALLOC_FREE_BLOCKS (vpaths); + ALLOC_FREE_BLOCKS (searchpaths); } VISIBLE void diff --git a/libs/util/segtext.c b/libs/util/segtext.c index d215cda30..812249811 100644 --- a/libs/util/segtext.c +++ b/libs/util/segtext.c @@ -213,3 +213,16 @@ Segtext_Find (const segtext_t *st, const char *tag) return chunk->text; return 0; } + +static void +segtext_shutdown (void *data) +{ + ALLOC_FREE_BLOCKS (chunks); + ALLOC_FREE_BLOCKS (texts); +} + +static void __attribute__((constructor)) +segtext_init (void) +{ + Sys_RegisterShutdown (segtext_shutdown, 0); +} diff --git a/libs/util/set.c b/libs/util/set.c index 0fe8fe2ec..20f92c01d 100644 --- a/libs/util/set.c +++ b/libs/util/set.c @@ -721,3 +721,16 @@ set_as_string (const set_t *set) dstring_clearstr (str); return set_to_dstring_r (&static_set_pool, str, set); } + +static void +set_shutdown (void *data) +{ + ALLOC_FREE_BLOCKS (static_set_pool.set); + ALLOC_FREE_BLOCKS (static_set_pool.set_iter); +} + +static void __attribute__((constructor)) +set_init (void) +{ + Sys_RegisterShutdown (set_shutdown, 0); +} diff --git a/libs/util/sys.c b/libs/util/sys.c index 6902525c7..a89053a6d 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -536,22 +536,6 @@ Sys_Init_Cvars (void) Cvar_Register (&sys_sleep_cvar, 0, 0); } -void -Sys_Shutdown (void) -{ - shutdown_list_t *t; - - while (shutdown_list) { - void (*func) (void *) = shutdown_list->func; - void *data = shutdown_list->data; - t = shutdown_list; - shutdown_list = shutdown_list->next; - free (t); - - func (data); - } -} - VISIBLE void Sys_Quit (void) { @@ -1231,3 +1215,45 @@ Sys_UniqueFile (dstring_t *name, const char *prefix, const char *suffix, seq++; } } + +void +Sys_Shutdown (void) +{ + shutdown_list_t *t; + + while (shutdown_list) { + void (*func) (void *) = shutdown_list->func; + void *data = shutdown_list->data; + t = shutdown_list; + shutdown_list = shutdown_list->next; + free (t); + + func (data); + } + while (free_sh) { + __auto_type t = free_sh->next; + free (free_sh); + free_sh = t; + } + while (sh_stack) { + __auto_type t = sh_stack->next; + free (sh_stack); + sh_stack = t; + } + while (error_handler_freelist) { + __auto_type t = error_handler_freelist->next; + free (error_handler_freelist); + error_handler_freelist = t; + } + while (error_handler) { + __auto_type t = error_handler->next; + free (error_handler); + error_handler = t; + } + if (sys_print_msg) { + dstring_delete (sys_print_msg); + } + if (sys_debuglog_data) { + dstring_delete (sys_debuglog_data); + } +} diff --git a/libs/util/test/test-seg.c b/libs/util/test/test-seg.c index d67001394..c898abcc6 100644 --- a/libs/util/test/test-seg.c +++ b/libs/util/test/test-seg.c @@ -11,6 +11,7 @@ #include #include "QF/segtext.h" +#include "QF/sys.h" static const char *test_string = "blah\n" @@ -83,5 +84,7 @@ main (int argc, const char **argv) res = 1; } } + Segtext_delete (st); + Sys_Shutdown (); return res; } diff --git a/libs/util/va.c b/libs/util/va.c index b47d5d2ba..98af3d8b0 100644 --- a/libs/util/va.c +++ b/libs/util/va.c @@ -38,6 +38,7 @@ #include #include "QF/dstring.h" +#include "QF/sys.h" #include "QF/va.h" struct va_ctx_s { @@ -46,6 +47,8 @@ struct va_ctx_s { int str_index; }; +static va_ctx_t *default_va_ctx; + VISIBLE va_ctx_t * va_create_context (int buffers) { @@ -74,15 +77,14 @@ va_destroy_context (va_ctx_t *ctx) VISIBLE const char * va (va_ctx_t *ctx, const char *fmt, ...) { - static va_ctx_t *_ctx; va_list args; dstring_t *dstr; if (!ctx) { - if (!_ctx) { - _ctx = va_create_context (4); + if (!default_va_ctx) { + default_va_ctx = va_create_context (4); } - ctx = _ctx; + ctx = default_va_ctx; } dstr = ctx->strings[ctx->str_index++ % ctx->num_strings]; @@ -107,3 +109,17 @@ nva (const char *fmt, ...) return dstring_freeze (string); } + +static void +va_shutdown (void *data) +{ + if (default_va_ctx) { + va_destroy_context (default_va_ctx); + } +} + +static void __attribute__((constructor)) +va_init (void) +{ + Sys_RegisterShutdown (va_shutdown, 0); +}