From bd5637af6d4a5f318bedf9912b931b9338f89c1a Mon Sep 17 00:00:00 2001 From: David Chisnall Date: Sat, 30 Mar 2019 10:48:30 +0000 Subject: [PATCH] Fix memory leak in @synchronized. This was actually a memory leak in the hidden class implementation, but it was mostly visible in the @synchronized implementation. Every hidden class registered a custom .cxx_destruct method, to handle cleanup of all of the hidden class structures. Unfortunately, this destructor failed to delete the reflection metadata structures associated with the class, specifically the objc_method_list containing the objc_method pointing to the destructor itself. Fixes #98 --- associate.m | 3 +++ class.h | 9 +++++++++ runtime.c | 4 ++-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/associate.m b/associate.m index cf8865d..a342475 100644 --- a/associate.m +++ b/associate.m @@ -275,6 +275,9 @@ static void deallocHiddenClass(id obj, SEL _cmd) } } obj->isa = hiddenClass->super_class; + // Free the introspection structures: + freeMethodLists(hiddenClass); + freeIvarLists(hiddenClass); // Free the class free(hiddenClass); } diff --git a/class.h b/class.h index d2e947c..44ed65f 100644 --- a/class.h +++ b/class.h @@ -434,4 +434,13 @@ static inline BOOL classIsOrInherits(Class cls, Class base) return NO; } +/** + * Free the instance variable lists associated with a class. + */ +void freeIvarLists(Class aClass); +/** + * Free the method lists associated with a class. + */ +void freeMethodLists(Class aClass); + #endif //__OBJC_CLASS_H_INCLUDED diff --git a/runtime.c b/runtime.c index 1b6f126..245ef03 100644 --- a/runtime.c +++ b/runtime.c @@ -622,7 +622,7 @@ id objc_getRequiredClass(const char *name) return cls; } -static void freeMethodLists(Class aClass) +PRIVATE void freeMethodLists(Class aClass) { struct objc_method_list *methods = aClass->methods; while(methods != NULL) @@ -637,7 +637,7 @@ static void freeMethodLists(Class aClass) } } -static void freeIvarLists(Class aClass) +PRIVATE void freeIvarLists(Class aClass) { struct objc_ivar_list *ivarlist = aClass->ivars; if (NULL == ivarlist) { return; }