From a56f51099c3ad52665922a102439bc4d7507b021 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 4 Sep 2016 21:15:22 +0200 Subject: [PATCH 01/10] use test_setup in seen.test --- src/seen.test.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/seen.test.c b/src/seen.test.c index 504d79ada..66a476135 100644 --- a/src/seen.test.c +++ b/src/seen.test.c @@ -23,7 +23,7 @@ static void test_add_seen(CuTest *tc) { region *r; seen_region **seen, *sr; - test_cleanup(); + test_setup(); seen = seen_init(); r = test_create_region(0, 0, 0); sr = add_seen(seen, r, see_travel, false); @@ -47,7 +47,7 @@ static void test_faction_add_seen(CuTest *tc) { faction *f; seen_region *sr; - test_cleanup(); + test_setup(); f = test_create_faction(0); f->seen = seen_init(); test_create_region(0, 0, 0); @@ -65,7 +65,7 @@ static void test_prepare_seen(CuTest *tc) { faction *f; unit *u; - test_cleanup(); + test_setup(); f = test_create_faction(0); r = test_create_region(0, 0, 0); u = test_create_unit(f, r); @@ -90,7 +90,7 @@ static void test_seen_travelthru(CuTest *tc) { faction *f; unit *u; - test_cleanup(); + test_setup(); setup_seen(0, 0); r = test_create_region(0, 0, 0); f = test_create_faction(0); @@ -116,7 +116,7 @@ static void test_seen_region(CuTest *tc) { seen_region **seen, *sr; region *r; - test_cleanup(); + test_setup(); setup_seen(0, 0); r = test_create_region(0, 0, 0); seen = seen_init(); @@ -131,7 +131,7 @@ static void test_seen_interval_backward(CuTest *tc) { region *r, *first, *last; seen_region **seen; - test_cleanup(); + test_setup(); r = test_create_region(0, 0, 0); setup_seen(0, 0); seen = seen_init(); @@ -150,7 +150,7 @@ static void test_seen_interval_forward(CuTest *tc) { region *r, *first, *last; seen_region **seen; - test_cleanup(); + test_setup(); setup_seen(0, 0); r = test_create_region(0, 0, 0); seen = seen_init(); @@ -175,7 +175,7 @@ static void test_seenhash_map(CuTest *tc) { seen_region **seen; int i = 0; - test_cleanup(); + test_setup(); seen = seen_init(); r = test_create_region(1, 1, 0); add_seen(seen, r, see_unit, false); From a5b3fad67a1b182181805506a632c08e07a1fcfd Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 4 Sep 2016 20:27:36 +0100 Subject: [PATCH 02/10] skeleton of a language test, try to find init_direction memory leak. --- src/test_eressea.c | 1 + src/util/CMakeLists.txt | 2 +- src/util/language.test.c | 20 ++++++++++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 src/util/language.test.c diff --git a/src/test_eressea.c b/src/test_eressea.c index 3001ee2b8..18eafcf3a 100644 --- a/src/test_eressea.c +++ b/src/test_eressea.c @@ -76,6 +76,7 @@ int RunAllTests(int argc, char *argv[]) ADD_SUITE(bsdstring); ADD_SUITE(functions); ADD_SUITE(gamedata); + ADD_SUITE(language); ADD_SUITE(parser); ADD_SUITE(password); ADD_SUITE(umlaut); diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index 65aae942d..7eda87132 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -11,7 +11,7 @@ bsdstring.test.c functions.test.c gamedata.test.c # goodies.test.c -# language.test.c +language.test.c # lists.test.c # log.test.c # message.test.c diff --git a/src/util/language.test.c b/src/util/language.test.c new file mode 100644 index 000000000..20e6314cc --- /dev/null +++ b/src/util/language.test.c @@ -0,0 +1,20 @@ +#include +#include +#include "language.h" + +#include +#include + +static void test_language(CuTest *tc) +{ + test_setup(); + + test_cleanup(); +} + +CuSuite *get_language_suite(void) +{ + CuSuite *suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_language); + return suite; +} From 19d490ce71fd8c5cc6db7b2a1c2fec585f599a14 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 4 Sep 2016 22:07:52 +0200 Subject: [PATCH 03/10] test_create_locale leaks memory. adding a simple test that shows this (under valgrind). --- src/util/language.test.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/util/language.test.c b/src/util/language.test.c index 20e6314cc..d86f1b2a7 100644 --- a/src/util/language.test.c +++ b/src/util/language.test.c @@ -5,10 +5,15 @@ #include #include +extern const char *directions[]; + static void test_language(CuTest *tc) { + const char *str; test_setup(); - + default_locale = test_create_locale(); + str = directions[1]; + CuAssertStrEquals(tc, str, locale_getstring(default_locale, str)); test_cleanup(); } From b2b9b9eae4e26db8996c6f4d91766cece485622d Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 4 Sep 2016 21:52:09 +0100 Subject: [PATCH 04/10] test having more than one name per direction. use test_setup. --- src/direction.test.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/direction.test.c b/src/direction.test.c index c2feebd3f..b7516a8e6 100644 --- a/src/direction.test.c +++ b/src/direction.test.c @@ -10,7 +10,7 @@ static void test_init_directions(CuTest *tc) { struct locale *lang; - test_cleanup(); + test_setup(); lang = get_or_create_locale("de"); locale_setstring(lang, "dir_nw", "NW"); init_directions(lang); @@ -20,19 +20,23 @@ static void test_init_directions(CuTest *tc) { static void test_init_direction(CuTest *tc) { struct locale *lang; - test_cleanup(); + test_setup(); lang = get_or_create_locale("de"); init_direction(lang, D_NORTHWEST, "NW"); + init_direction(lang, D_NORTHWEST, "northwest"); init_direction(lang, D_EAST, "OST"); + init_direction(lang, D_EAST, "O"); CuAssertIntEquals(tc, D_NORTHWEST, get_direction("nw", lang)); + CuAssertIntEquals(tc, D_NORTHWEST, get_direction("northwest", lang)); CuAssertIntEquals(tc, D_EAST, get_direction("ost", lang)); + CuAssertIntEquals(tc, D_EAST, get_direction("O", lang)); CuAssertIntEquals(tc, NODIRECTION, get_direction("east", lang)); test_cleanup(); } static void test_finddirection(CuTest *tc) { - test_cleanup(); + test_setup(); CuAssertIntEquals(tc, D_SOUTHWEST, finddirection("southwest")); CuAssertIntEquals(tc, D_SOUTHEAST, finddirection("southeast")); CuAssertIntEquals(tc, D_NORTHWEST, finddirection("northwest")); @@ -42,6 +46,7 @@ static void test_finddirection(CuTest *tc) { CuAssertIntEquals(tc, D_PAUSE, finddirection("pause")); CuAssertIntEquals(tc, NODIRECTION, finddirection("")); CuAssertIntEquals(tc, NODIRECTION, finddirection("potato")); + test_cleanup(); } CuSuite *get_direction_suite(void) From 7b5383dfffebb6c3a54e5889283f6891ecd3698c Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 5 Sep 2016 17:57:59 +0200 Subject: [PATCH 05/10] disable all direction tests instead of the minimal leak proof --- src/CMakeLists.txt | 1 + src/direction.test.c | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a0e1325b9..374eba608 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -17,6 +17,7 @@ IF(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pedantic -Wsign-compare -Wall -Werror -Wno-unknown-pragmas -Wstrict-prototypes -Wpointer-arith -Wno-char-subscripts -Wno-long-long") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error=unused-but-set-variable") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -DHAVE__BOOL") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-function") ELSEIF(MSVC) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Wall /WX /MP") set(CMAKE_EXE_LINKER_FLAGS_DEBUG diff --git a/src/direction.test.c b/src/direction.test.c index b7516a8e6..e5c55f3d8 100644 --- a/src/direction.test.c +++ b/src/direction.test.c @@ -3,6 +3,7 @@ #include "direction.h" #include "tests.h" +#include #include #include @@ -18,6 +19,21 @@ static void test_init_directions(CuTest *tc) { test_cleanup(); } +static void test_leak(CuTest *tc) { + struct locale *lang; + void **tokens; + variant token; + + test_setup(); + lang = get_or_create_locale("de"); + tokens = get_translations(lang, UT_DIRECTIONS); + token.i = D_NORTHWEST; + addtoken(tokens, "NW", token); + addtoken(tokens, "northwest", token); + + test_cleanup(); +} + static void test_init_direction(CuTest *tc) { struct locale *lang; test_setup(); @@ -52,9 +68,12 @@ static void test_finddirection(CuTest *tc) { CuSuite *get_direction_suite(void) { CuSuite *suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_leak); + /* SUITE_ADD_TEST(suite, test_init_direction); SUITE_ADD_TEST(suite, test_init_directions); SUITE_ADD_TEST(suite, test_finddirection); + */ return suite; } From fa6a3e377d22dbab78928380a42fb67e60f3e503 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 5 Sep 2016 18:46:02 +0200 Subject: [PATCH 06/10] relocate the addtoken leak "test" to umlaut.test.c --- src/CMakeLists.txt | 1 - src/direction.test.c | 18 ------------------ src/util/umlaut.test.c | 11 +++++++++++ 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 374eba608..a0e1325b9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -17,7 +17,6 @@ IF(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pedantic -Wsign-compare -Wall -Werror -Wno-unknown-pragmas -Wstrict-prototypes -Wpointer-arith -Wno-char-subscripts -Wno-long-long") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error=unused-but-set-variable") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -DHAVE__BOOL") - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-function") ELSEIF(MSVC) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Wall /WX /MP") set(CMAKE_EXE_LINKER_FLAGS_DEBUG diff --git a/src/direction.test.c b/src/direction.test.c index e5c55f3d8..bf50df6bf 100644 --- a/src/direction.test.c +++ b/src/direction.test.c @@ -19,21 +19,6 @@ static void test_init_directions(CuTest *tc) { test_cleanup(); } -static void test_leak(CuTest *tc) { - struct locale *lang; - void **tokens; - variant token; - - test_setup(); - lang = get_or_create_locale("de"); - tokens = get_translations(lang, UT_DIRECTIONS); - token.i = D_NORTHWEST; - addtoken(tokens, "NW", token); - addtoken(tokens, "northwest", token); - - test_cleanup(); -} - static void test_init_direction(CuTest *tc) { struct locale *lang; test_setup(); @@ -68,12 +53,9 @@ static void test_finddirection(CuTest *tc) { CuSuite *get_direction_suite(void) { CuSuite *suite = CuSuiteNew(); - SUITE_ADD_TEST(suite, test_leak); - /* SUITE_ADD_TEST(suite, test_init_direction); SUITE_ADD_TEST(suite, test_init_directions); SUITE_ADD_TEST(suite, test_finddirection); - */ return suite; } diff --git a/src/util/umlaut.test.c b/src/util/umlaut.test.c index 577b7059a..d903c6fea 100644 --- a/src/util/umlaut.test.c +++ b/src/util/umlaut.test.c @@ -97,6 +97,16 @@ static void test_umlaut(CuTest * tc) freetokens(tokens); } +static void test_leak(CuTest *tc) { + void *tokens = NULL; + variant token; + + token.i = 42; + addtoken(&tokens, "NW", token); + addtoken(&tokens, "northwest", token); + freetokens(tokens); +} + CuSuite *get_umlaut_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -104,5 +114,6 @@ CuSuite *get_umlaut_suite(void) SUITE_ADD_TEST(suite, test_directions); SUITE_ADD_TEST(suite, test_transliterate); SUITE_ADD_TEST(suite, test_transliterations); + SUITE_ADD_TEST(suite, test_leak); return suite; } From c525553c49fac191d53c112c56aff2b6a0de3890 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 5 Sep 2016 17:48:54 +0100 Subject: [PATCH 07/10] unused variable --- src/util/umlaut.test.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/util/umlaut.test.c b/src/util/umlaut.test.c index d903c6fea..280e83e3c 100644 --- a/src/util/umlaut.test.c +++ b/src/util/umlaut.test.c @@ -104,6 +104,7 @@ static void test_leak(CuTest *tc) { token.i = 42; addtoken(&tokens, "NW", token); addtoken(&tokens, "northwest", token); + CuAssertIntEquals(tc, E_TOK_SUCCESS, findtoken(tokens, "n", &token)); freetokens(tokens); } From b62fa64d8c892895a583ca940dcb1410890e7a4d Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 5 Sep 2016 20:05:36 +0200 Subject: [PATCH 08/10] closer leak debugging --- src/util/umlaut.test.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/util/umlaut.test.c b/src/util/umlaut.test.c index 280e83e3c..1bb93ac4b 100644 --- a/src/util/umlaut.test.c +++ b/src/util/umlaut.test.c @@ -4,6 +4,7 @@ #include #include "umlaut.h" +#ifdef LEAK_FREE static void test_transliterate(CuTest * tc) { char buffer[32]; @@ -96,14 +97,15 @@ static void test_umlaut(CuTest * tc) freetokens(tokens); } +#endif static void test_leak(CuTest *tc) { void *tokens = NULL; variant token; token.i = 42; - addtoken(&tokens, "NW", token); - addtoken(&tokens, "northwest", token); + addtoken(&tokens, "No", token); + addtoken(&tokens, "nw", token); CuAssertIntEquals(tc, E_TOK_SUCCESS, findtoken(tokens, "n", &token)); freetokens(tokens); } @@ -111,10 +113,12 @@ static void test_leak(CuTest *tc) { CuSuite *get_umlaut_suite(void) { CuSuite *suite = CuSuiteNew(); +#ifdef LEAK_FREE SUITE_ADD_TEST(suite, test_umlaut); SUITE_ADD_TEST(suite, test_directions); SUITE_ADD_TEST(suite, test_transliterate); SUITE_ADD_TEST(suite, test_transliterations); +#endif SUITE_ADD_TEST(suite, test_leak); return suite; } From a5ce809f4151859c3626a37c0f2e6513af629212 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 6 Sep 2016 19:57:07 +0100 Subject: [PATCH 09/10] fix memory leak in umlaut.c with reference counting (sad). --- src/direction.c | 4 ++-- src/kernel/building.c | 2 +- src/kernel/command.c | 2 +- src/kernel/config.c | 10 +++++----- src/kernel/ship.c | 2 +- src/laws.c | 4 ++-- src/magic.c | 2 +- src/util/umlaut.c | 36 +++++++++++++++++++++++------------- src/util/umlaut.h | 5 +++-- src/util/umlaut.test.c | 14 +++++--------- src/vortex.c | 2 +- 11 files changed, 45 insertions(+), 38 deletions(-) diff --git a/src/direction.c b/src/direction.c index 0b9bb8206..5e2333bbe 100644 --- a/src/direction.c +++ b/src/direction.c @@ -12,7 +12,7 @@ void init_direction(const struct locale *lang, direction_t dir, const char *str) void **tokens = get_translations(lang, UT_DIRECTIONS); variant token; token.i = dir; - addtoken(tokens, str, token); + addtoken((struct tnode **)tokens, str, token); } void init_directions(struct locale *lang) { @@ -47,7 +47,7 @@ void init_directions(struct locale *lang) { if (str) { variant token; token.i = dirs[i].direction; - addtoken(tokens, str, token); + addtoken((struct tnode **)tokens, str, token); } } } diff --git a/src/kernel/building.c b/src/kernel/building.c index 11ab70bb1..e4ae8f991 100644 --- a/src/kernel/building.c +++ b/src/kernel/building.c @@ -311,7 +311,7 @@ const building_type *findbuildingtype(const char *name, const char *n = LOC(lang, btype->_name); type.v = (void *)btype; - addtoken(&bn->names, n, type); + addtoken((struct tnode **)&bn->names, n, type); } bnames = bn; } diff --git a/src/kernel/command.c b/src/kernel/command.c index 0642be060..a667edabc 100644 --- a/src/kernel/command.c +++ b/src/kernel/command.c @@ -78,7 +78,7 @@ const char *str, parser fun) cmd->fun = fun; cmd->nodes = tnext; var.v = cmd; - addtoken(keys, str, var); + addtoken((struct tnode **)keys, str, var); } static int do_command_i(const void *keys, struct unit *u, struct order *ord) diff --git a/src/kernel/config.c b/src/kernel/config.c index e3918557e..4758b36c8 100644 --- a/src/kernel/config.c +++ b/src/kernel/config.c @@ -471,7 +471,7 @@ void init_terrains_translation(const struct locale *lang) { var.v = (void *)terrain; name = locale_string(lang, terrain->_name, false); if (name) { - addtoken(tokens, name, var); + addtoken((struct tnode **)tokens, name, var); } else { log_debug("no translation for terrain %s in locale %s", terrain->_name, locale_name(lang)); @@ -490,7 +490,7 @@ void init_options_translation(const struct locale * lang) { if (options[i]) { const char *name = locale_string(lang, options[i], false); if (name) { - addtoken(tokens, name, var); + addtoken((struct tnode **)tokens, name, var); } else { log_debug("no translation for OPTION %s in locale %s", options[i], locale_name(lang)); @@ -525,7 +525,7 @@ void init_locale(struct locale *lang) var.i = i; name = LOC(lang, mkname("school", tok)); if (name) { - addtoken(tokens, name, var); + addtoken((struct tnode **)tokens, name, var); } else { log_warning("no translation for magic school %s in locale %s", tok, locale_name(lang)); @@ -544,9 +544,9 @@ void init_locale(struct locale *lang) const char *name; var.v = (void *)rc; name = locale_string(lang, rc_name_s(rc, NAME_PLURAL), false); - if (name) addtoken(tokens, name, var); + if (name) addtoken((struct tnode **)tokens, name, var); name = locale_string(lang, rc_name_s(rc, NAME_SINGULAR), false); - if (name) addtoken(tokens, name, var); + if (name) addtoken((struct tnode **)tokens, name, var); } init_parameters(lang); diff --git a/src/kernel/ship.c b/src/kernel/ship.c index fb2fb3906..02a980b68 100644 --- a/src/kernel/ship.c +++ b/src/kernel/ship.c @@ -78,7 +78,7 @@ const ship_type *findshiptype(const char *name, const struct locale *lang) variant var2; const char *n = LOC(lang, stype->_name); var2.v = (void *)stype; - addtoken(&sn->names, n, var2); + addtoken((struct tnode **)&sn->names, n, var2); } snames = sn; } diff --git a/src/laws.c b/src/laws.c index e41bafbec..197433bfa 100755 --- a/src/laws.c +++ b/src/laws.c @@ -1438,8 +1438,8 @@ static void init_prefixnames(void) LOC(lang, mkname("prefix", race_prefixes[key])); if (findtoken(in->names, pname, &var) == E_TOK_NOMATCH || var.i != key) { var.i = key; - addtoken(&in->names, pname, var); - addtoken(&in->names, LOC(lang, mkname("prefix", + addtoken((struct tnode **)&in->names, pname, var); + addtoken((struct tnode **)&in->names, LOC(lang, mkname("prefix", race_prefixes[key])), var); } } diff --git a/src/magic.c b/src/magic.c index d24612e06..6ff2ac8e5 100644 --- a/src/magic.c +++ b/src/magic.c @@ -2954,7 +2954,7 @@ static void select_spellbook(void **tokens, spellbook *sb, const struct locale * else { variant token; token.v = sp; - addtoken(tokens, n, token); + addtoken((struct tnode **)tokens, n, token); } } } diff --git a/src/util/umlaut.c b/src/util/umlaut.c index 9c37b852c..6be0bdde5 100644 --- a/src/util/umlaut.c +++ b/src/util/umlaut.c @@ -32,7 +32,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. typedef struct tref { struct tref *nexthash; ucs4_t ucs; - void *node; + struct tnode *node; } tref; #define LEAF 1 /* leaf node for a word. always matches */ @@ -42,6 +42,7 @@ typedef struct tnode { struct tref *next[NODEHASHSIZE]; unsigned char flags; variant id; + int refcount; } tnode; char * transliterate(char * out, size_t size, const char * in) @@ -114,7 +115,13 @@ char * transliterate(char * out, size_t size, const char * in) return *src ? 0 : out; } -void addtoken(void ** root, const char *str, variant id) +tnode * mknode(void) { + tnode * node = calloc(1, sizeof(tnode)); + node->refcount = 1; + return node; +} + +void addtoken(tnode ** root, const char *str, variant id) { tnode * tk; static const struct replace { @@ -128,7 +135,7 @@ void addtoken(void ** root, const char *str, variant id) assert(root && str); if (!*root) { - tk = *root = calloc(1, sizeof(tnode)); + tk = *root = mknode(); } else { tk = *root; @@ -161,7 +168,7 @@ void addtoken(void ** root, const char *str, variant id) next = next->nexthash; if (!next) { tref *ref; - tnode *node = (tnode *)calloc(1, sizeof(tnode)); // TODO: what is the reason for this empty node to exist? + tnode *node = mknode(); // TODO: what is the reason for this empty node to exist? if (ucs < 'a' || ucs > 'z') { lcs = towlower((wint_t)ucs); @@ -187,6 +194,7 @@ void addtoken(void ** root, const char *str, variant id) assert_alloc(ref); ref->ucs = lcs; ref->node = node; + ++node->refcount; ref->nexthash = tk->next[index]; tk->next[index] = ref; } @@ -212,23 +220,25 @@ void addtoken(void ** root, const char *str, variant id) } } -void freetokens(void * root) +void freetokens(tnode * root) { - tnode * node = (tnode *)root; + tnode * node = root; int i; for (i = 0; node && i != NODEHASHSIZE; ++i) { if (node->next[i]) { - tref ** refs = &node->next[i]; - freetokens(node->next[i]->node); - while (*refs) { - tref * ref = *refs; - *refs = ref->nexthash; -// free(ref->node); + tref * ref = node->next[i]; + while (ref) { + tref * next = ref->nexthash; + freetokens(ref->node); free(ref); + ref = next; } + node->next[i] = 0; } } - free(node); + if (--node->refcount == 0) { + free(node); + } } int findtoken(const void * root, const char *key, variant * result) diff --git a/src/util/umlaut.h b/src/util/umlaut.h index 1e6baecb4..d64df7609 100644 --- a/src/util/umlaut.h +++ b/src/util/umlaut.h @@ -29,10 +29,11 @@ extern "C" { #define E_TOK_NOMATCH (-1) #define E_TOK_SUCCESS 0 #define NODEHASHSIZE 8 + struct tnode; int findtoken(const void *tk, const char *str, variant * result); - void addtoken(void **root, const char *str, variant id); - void freetokens(void *root); + void addtoken(struct tnode **root, const char *str, variant id); + void freetokens(struct tnode *root); char * transliterate(char * out, size_t size, const char * in); diff --git a/src/util/umlaut.test.c b/src/util/umlaut.test.c index 1bb93ac4b..959960509 100644 --- a/src/util/umlaut.test.c +++ b/src/util/umlaut.test.c @@ -4,7 +4,6 @@ #include #include "umlaut.h" -#ifdef LEAK_FREE static void test_transliterate(CuTest * tc) { char buffer[32]; @@ -29,7 +28,7 @@ static void test_transliterate(CuTest * tc) static void test_transliterations(CuTest *tc) { const char * umlauts = "\xc3\xa4\xc3\xb6\xc3\xbc\xc3\x9f"; /* auml ouml uuml szlig nul */ - void * tokens = 0; + struct tnode * tokens = 0; variant id; int result; @@ -49,7 +48,7 @@ static void test_transliterations(CuTest *tc) { static void test_directions(CuTest * tc) { - void * tokens = 0; + struct tnode * tokens = 0; variant id; int result; @@ -65,7 +64,7 @@ static void test_directions(CuTest * tc) static void test_umlaut(CuTest * tc) { - void * tokens = 0; + struct tnode *tokens = 0; variant id; int result; @@ -97,14 +96,13 @@ static void test_umlaut(CuTest * tc) freetokens(tokens); } -#endif static void test_leak(CuTest *tc) { - void *tokens = NULL; + struct tnode *tokens = NULL; variant token; token.i = 42; - addtoken(&tokens, "No", token); + addtoken(&tokens, "NO", token); addtoken(&tokens, "nw", token); CuAssertIntEquals(tc, E_TOK_SUCCESS, findtoken(tokens, "n", &token)); freetokens(tokens); @@ -113,12 +111,10 @@ static void test_leak(CuTest *tc) { CuSuite *get_umlaut_suite(void) { CuSuite *suite = CuSuiteNew(); -#ifdef LEAK_FREE SUITE_ADD_TEST(suite, test_umlaut); SUITE_ADD_TEST(suite, test_directions); SUITE_ADD_TEST(suite, test_transliterate); SUITE_ADD_TEST(suite, test_transliterations); -#endif SUITE_ADD_TEST(suite, test_leak); return suite; } diff --git a/src/vortex.c b/src/vortex.c index 8aac12aec..4b512476b 100644 --- a/src/vortex.c +++ b/src/vortex.c @@ -36,7 +36,7 @@ void register_special_direction(struct locale *lang, const char *name) char *str = _strdup(name); var.v = str; - addtoken(tokens, token, var); + addtoken((struct tnode **)tokens, token, var); if (lang == locales) { dir_lookup *dl = malloc(sizeof(dir_lookup)); From 00804344fd2a07ee5de07192ac1780ee385011f3 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 6 Sep 2016 21:07:23 +0200 Subject: [PATCH 10/10] fix order-related memory leaks --- src/kernel/build.test.c | 6 +++--- src/piracy.c | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/kernel/build.test.c b/src/kernel/build.test.c index 65e651010..c0775051e 100644 --- a/src/kernel/build.test.c +++ b/src/kernel/build.test.c @@ -282,7 +282,7 @@ static void test_build_destroy_road(CuTest *tc) r = test_create_region(0, 0, 0); rsetroad(r, D_EAST, 100); u = test_create_unit(f = test_create_faction(0), r); - ord = create_order(K_DESTROY, f->locale, "%s %s", LOC(f->locale, parameters[P_ROAD]), LOC(f->locale, directions[D_EAST])); + u->orders = ord = create_order(K_DESTROY, f->locale, "%s %s", LOC(f->locale, parameters[P_ROAD]), LOC(f->locale, directions[D_EAST])); CuAssertIntEquals(tc, 0, destroy_cmd(u, ord)); CuAssertIntEquals(tc, 100, rroad(r, D_EAST)); @@ -336,7 +336,7 @@ static void test_build_destroy_road_guard(CuTest *tc) rsetroad(r, D_EAST, 100); ug = test_create_guard(r, 0, 0); u = test_create_unit(f = test_create_faction(0), r); - ord = create_order(K_DESTROY, f->locale, "%s %s", LOC(f->locale, parameters[P_ROAD]), LOC(f->locale, directions[D_EAST])); + u->orders = ord = create_order(K_DESTROY, f->locale, "%s %s", LOC(f->locale, parameters[P_ROAD]), LOC(f->locale, directions[D_EAST])); set_level(u, SK_ROAD_BUILDING, 1); CuAssertIntEquals(tc, 0, destroy_cmd(u, ord)); @@ -367,7 +367,7 @@ static void test_build_destroy_road_limit(CuTest *tc) r = test_create_region(0, 0, 0); rsetroad(r, D_EAST, 100); u = test_create_unit(f = test_create_faction(0), r); - ord = create_order(K_DESTROY, f->locale, "1 %s %s", LOC(f->locale, parameters[P_ROAD]), LOC(f->locale, directions[D_EAST])); + u->orders = ord = create_order(K_DESTROY, f->locale, "1 %s %s", LOC(f->locale, parameters[P_ROAD]), LOC(f->locale, directions[D_EAST])); set_level(u, SK_ROAD_BUILDING, 1); CuAssertIntEquals(tc, 0, destroy_cmd(u, ord)); diff --git a/src/piracy.c b/src/piracy.c index 8af0b899e..b2f96c596 100644 --- a/src/piracy.c +++ b/src/piracy.c @@ -209,6 +209,7 @@ void piracy_cmd(unit * u) /* Bewegung ausführen */ init_order(ord); move_cmd(u, ord); + free_order(ord); } void age_piracy(region *r) {