From 072c17f315536ec5f77aebf7508f0aaf8796c8e4 Mon Sep 17 00:00:00 2001 From: rfm Date: Fri, 15 Nov 2024 12:28:14 +0000 Subject: [PATCH] Add some consistecy checks --- Headers/GNUstepBase/NSObject+GNUstepBase.h | 32 +++++---- Source/Additions/NSObject+GNUstepBase.m | 76 ++++++++++++++++------ 2 files changed, 77 insertions(+), 31 deletions(-) diff --git a/Headers/GNUstepBase/NSObject+GNUstepBase.h b/Headers/GNUstepBase/NSObject+GNUstepBase.h index 150b5838f..ec0617358 100644 --- a/Headers/GNUstepBase/NSObject+GNUstepBase.h +++ b/Headers/GNUstepBase/NSObject+GNUstepBase.h @@ -241,21 +241,31 @@ extern "C" { */ + (BOOL) isExiting; -/** This method informs the system that anAddress is a pointer whose content - * has been leaked and should be released and zeroed out (if clean-up is - * enabled) at process exit. If the content of the location is changed - * between the point where this method is called and the process exits, - * then the new content of the address is what will be released on clean-up. +/** This method informs the system that anObject should be retained to + * persist until the process exits. If clean-up is enabled the object + * should be released upon process exit. + * If this method is called while the process is already existing it + * returns nil, otherwise it returnes the retained argument. + * Raises an exception if anObject has already been leaked or if it is + * nil (unless the process is exiting). + */ ++ (id) NS_RETURNS_RETAINED leak: (id)anObject; + +/** This method informs the system that the object at anAddress has been + * retained to persist until the process exits. If clean-up is enabled + * the object should be released (and the address content zeroed out) + * upon process exit. + * If this method is called while the process is already existing it releases + * the object and zeros out the memory location then returns nil, otherwise + * it returns the object found at the memory location. + * Raises an exception if anAddress (or the object at anAddress) has already + * been leaked or if it is nil (unless the process is exiting). */ + (void) leaked: (id*)anAddress; -/** Deprecated: use +leaked: instead. +/** DEPRECATED ... use +leaked: instead. */ -+ (id) NS_RETURNS_RETAINED leak: (id)anObject GS_DEPRECATED_FUNC; - -/** Deprecated: use +leaked: instead. - */ -+ (id) NS_RETURNS_RETAINED leakAt: (id*)anAddress ;//GS_DEPRECATED_FUNC; ++ (id) NS_RETURNS_RETAINED leakAt: (id*)anAddress; /** Sets the receiver to have its +atExit method called at the point when * the process terminates.
diff --git a/Source/Additions/NSObject+GNUstepBase.m b/Source/Additions/NSObject+GNUstepBase.m index d2c1c757b..25ce0d1c9 100644 --- a/Source/Additions/NSObject+GNUstepBase.m +++ b/Source/Additions/NSObject+GNUstepBase.m @@ -227,26 +227,9 @@ handleExit() return isExiting; } -+ (void) leaked: (id*)anAddress -{ - struct exitLink *l; - - NSAssert(*anAddress && [*anAddress isKindOfClass: [NSObject class]], - NSInvalidArgumentException); - l = (struct exitLink*)malloc(sizeof(struct exitLink)); - l->at = anAddress; - l->obj = *anAddress; - l->sel = 0; - setup(); - [exitLock lock]; - l->next = exited; - exited = l; - [exitLock unlock]; -} - + (id) leakAt: (id*)anAddress { - struct exitLink *l; + struct exitLink *l; l = (struct exitLink*)malloc(sizeof(struct exitLink)); l->at = anAddress; @@ -260,16 +243,69 @@ handleExit() return l->obj; } ++ (void) leaked: (id*)anAddress +{ + struct exitLink *l; + + NSAssert(anAddress != NULL, NSInvalidArgumentException); + if (isExiting) + { + [*anAddress release]; + *anAddress = nil; + return nil; + } + NSAssert([*anAddress isKindOfClass: [NSObject class]], + NSInvalidArgumentException); + setup(); + [exitLock lock]; + for (l = exited; l != NULL; l = l->next) + { + if (l->at == anAddress) + { + [exitLock unlock]; + [NSException raise: NSInvalidArgumentException + format: @"Repeated use of leak address %p", anAddress]; + } + if (*anAddress != nil && *anAddress == l->obj) + { + [exitLock unlock]; + [NSException raise: NSInvalidArgumentException + format: @"Repeated use of leak object %p", *anAddress]; + } + } + l = (struct exitLink*)malloc(sizeof(struct exitLink)); + l->at = anAddress; + l->obj = *anAddress; + l->sel = 0; + l->next = exited; + exited = l; + [exitLock unlock]; + return l->obj; +} + + (id) leak: (id)anObject { struct exitLink *l; + if (nil == anObject || isExiting) + { + return nil; + } + setup(); + [exitLock lock]; + for (l = exited; l != NULL; l = l->next) + { + if (l->obj == anObject || (l->at != nil && *l->at == anObject)) + { + [exitLock unlock]; + [NSException raise: NSInvalidArgumentException + format: @"Repeated use of leak object %p", anObject]; + } + } l = (struct exitLink*)malloc(sizeof(struct exitLink)); l->at = 0; l->obj = [anObject retain]; l->sel = 0; - setup(); - [exitLock lock]; l->next = exited; exited = l; [exitLock unlock];