Index: src/runtime/class.m ================================================================== --- src/runtime/class.m +++ src/runtime/class.m @@ -581,12 +581,12 @@ object_getClassName(id obj) { return object_getClass(obj)->name; } -static void -free_class(Class rcls) +void +objc_free_class(Class rcls) { struct objc_abi_class *cls = (struct objc_abi_class*)rcls; if (rcls->subclass_list != NULL) { free(rcls->subclass_list); @@ -598,10 +598,12 @@ rcls->dtable = NULL; if (rcls->superclass != Nil) cls->superclass = rcls->superclass->name; + + objc_hashtable_set(classes, cls->name, NULL); } void objc_free_all_classes(void) { @@ -610,13 +612,23 @@ if (classes == NULL) return; for (i = 0; i <= classes->last_idx; i++) { if (classes->data[i] != NULL) { - free_class((Class)classes->data[i]->obj); - free_class(((Class)classes->data[i]->obj)->isa); + Class cls = classes->data[i]->obj; + + if (cls == Nil) + continue; + + objc_free_class(cls); + objc_free_class(cls->isa); } } + + if (empty_dtable != NULL) { + objc_sparsearray_free(empty_dtable); + empty_dtable = NULL; + } objc_hashtable_free(classes); classes = NULL; } Index: src/runtime/runtime-private.h ================================================================== --- src/runtime/runtime-private.h +++ src/runtime/runtime-private.h @@ -128,10 +128,11 @@ extern void objc_free_all_categories(void); extern void objc_initialize_class(Class); extern void objc_update_dtable(Class); extern void objc_register_all_classes(struct objc_abi_symtab*); extern Class objc_classname_to_class(const char*); +extern void objc_free_class(Class); extern void objc_free_all_classes(void); extern uint32_t objc_hash_string(const char*); extern struct objc_hashtable* objc_hashtable_new(uint32_t); extern void objc_hashtable_set(struct objc_hashtable*, const char*, const void*); Index: src/runtime/sparsearray.m ================================================================== --- src/runtime/sparsearray.m +++ src/runtime/sparsearray.m @@ -194,14 +194,14 @@ #ifdef OF_SELUID24 uint_fast16_t j; #endif for (i = 0; i < 256; i++) { -#ifdef OF_SELUID24 if (s->buckets[i]->empty) continue; +#ifdef OF_SELUID24 for (j = 0; j < 256; j++) if (!s->buckets[i]->buckets[j]->empty) free(s->buckets[i]->buckets[j]); #endif Index: tests/TestsAppDelegate.m ================================================================== --- tests/TestsAppDelegate.m +++ tests/TestsAppDelegate.m @@ -13,10 +13,12 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #include "config.h" + +#include #import "OFString.h" #import "OFFile.h" #import "OFAutoreleasePool.h" @@ -30,10 +32,14 @@ #endif int main(int argc, char *argv[]) { +#ifdef OF_OBJFW_RUNTIME + atexit(objc_exit); +#endif + /* We need deterministic hashes for tests */ of_hash_seed = 0; return of_application_main(&argc, &argv, [TestsAppDelegate class]); } Index: tests/plugin/TestPlugin.m ================================================================== --- tests/plugin/TestPlugin.m +++ tests/plugin/TestPlugin.m @@ -15,10 +15,20 @@ */ #include "config.h" #import "TestPlugin.h" + +#ifdef OF_OBJFW_RUNTIME +# import "runtime-private.h" + +static void __attribute__((destructor)) +unload(void) +{ + objc_free_class(objc_getClass("TestPlugin")); +} +#endif @implementation TestPlugin - (int)test: (int)num { return num * 2;