From f6e83e64abbf76bbfddc90f885f7c3be379ecf2c Mon Sep 17 00:00:00 2001 From: Katharina Fey Date: Sun, 14 Jul 2019 18:41:07 +0100 Subject: Various improvements around HASH nodes The example previously would lead to corrupt memory when running for items that needed to re-hash the hash array. This has been fixed. Secondly, all HASH node memory leaks are now fixed, that resulted from badly tracking objects through the resize process. A new function `hash_free_shallow` was added to help with this. The function `array_free_shallow` is unused but might become useful in the future and so was not removed. The hash strategy is still garbage but this can be fixed later :) --- hash.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 7 deletions(-) (limited to 'hash.c') diff --git a/hash.c b/hash.c index 5ee4f90..f1abfb3 100644 --- a/hash.c +++ b/hash.c @@ -26,9 +26,9 @@ err_t hash_insert_key(struct bowl *self, char *key, struct bowl *child) // If the index is used, rescale and try again if(arr->ptr[idx] != NULL) { - struct bowl *prev = self; + struct bowl_arr *prev = arr; - // Allocate new array + // Allocate new hash array e = array_malloc(self, arr->size * 2); if(e) return e; @@ -41,12 +41,11 @@ err_t hash_insert_key(struct bowl *self, char *key, struct bowl *child) } } - e = array_free(prev); - if(e) return e; - e = hash_insert_key(self, key, child); if(e) return e; + hash_free_shallow(prev); + } else { hash_item *item = malloc(sizeof(hash_item)); CHECK(item, MALLOC_FAILED) @@ -58,6 +57,7 @@ err_t hash_insert_key(struct bowl *self, char *key, struct bowl *child) item->data = child; arr->ptr[idx] = (struct bowl*) item; + arr->used += 1; } return OK; @@ -65,7 +65,6 @@ err_t hash_insert_key(struct bowl *self, char *key, struct bowl *child) err_t hash_remove_key(struct bowl *self, char *key, struct bowl **child) { - CHECK(self, INVALID_STATE) CHECK(child, INVALID_STATE) CHECK(key, INVALID_STATE) @@ -79,7 +78,49 @@ err_t hash_remove_key(struct bowl *self, char *key, struct bowl **child) if(e) return e; (*child) = arr->ptr[idx]; + arr->used -= 1; arr->ptr[idx] = NULL; return OK; } - + +err_t hash_free(struct bowl *self) +{ + CHECK(self, INVALID_PARAMS) + struct bowl_arr *arr = self->_pl.array; + CHECK(arr, INVALID_PARAMS) + + err_t e = OK; + for(int i = 0; i < arr->size; i++) { + hash_item *item = (hash_item *) arr->ptr[i]; + if(item != NULL) { + CHECK(item->data, INVALID_STATE) + CHECK(item->key, INVALID_STATE) + + e = bowl_free(item->data); + if(e) break; + + free(item->key); + free(item); + } + } + + free(arr->ptr); + free(arr); + return e; +} + +err_t hash_free_shallow(struct bowl_arr *arr) +{ + CHECK(arr, INVALID_PARAMS); + for(int i = 0; i < arr->size; i++) { + hash_item *item = (hash_item *) arr->ptr[i]; + if(item != NULL) { + free(item->key); + free(item); + } + } + + free(arr->ptr); + free(arr); + return OK; +} -- cgit v1.2.3