Index: src/OFExceptions.h ================================================================== --- src/OFExceptions.h +++ src/OFExceptions.h @@ -9,10 +9,34 @@ * the packaging of this file. */ #import "OFObject.h" +/** + * An exception indicating an object could not be allocated. + * + * This exception is preallocated, as if there's no memory, no exception can + * be allocated of course. That's why you shouldn't and even can't free it. + * + * This is the only exception that is not an OFException as it's special. + * It does not know for which class allocation failed and it should not be + * handled like other exceptions, as the exception handling code is not + * allowed to allocate ANY memory. + */ +@interface OFAllocFailedException +{ + Class isa; +} + ++ (Class)class; + +/** + * \return An error message for the exception as a C string + */ +- (const char*)cString; +@end + /** * The OFException class is the base class for all exceptions in ObjFW. * * IMPORTANT: Exceptions do NOT use OFAutoreleasePools!! */ Index: src/OFExceptions.m ================================================================== --- src/OFExceptions.m +++ src/OFExceptions.m @@ -41,10 +41,22 @@ #import "OFExceptions.h" #ifndef HAVE_ASPRINTF #import "asprintf.h" #endif + +@implementation OFAllocFailedException ++ (Class)class +{ + return self; +} + +- (const char*)cString +{ + return "Allocating an object failed!"; +} +@end @implementation OFException + newWithClass: (Class)class_ { return [[self alloc] initWithClass: class_]; Index: src/OFObject.m ================================================================== --- src/OFObject.m +++ src/OFObject.m @@ -33,10 +33,14 @@ /* Hopefully no arch needs more than 16 bytes padding */ #define PRE_IVAR_ALIGN ((sizeof(struct pre_ivar) + 15) & ~15) #define PRE_IVAR ((struct pre_ivar*)((char*)self - PRE_IVAR_ALIGN)) +static struct { + Class isa; +} alloc_failed_exception; + @implementation OFObject #ifndef __objc_INCLUDE_GNU + load { return self; @@ -55,12 +59,14 @@ size_t isize = class_get_instance_size(self); #else size_t isize = class_getInstanceSize(self); #endif - if ((instance = malloc(isize + PRE_IVAR_ALIGN)) == NULL) - return nil; + if ((instance = malloc(isize + PRE_IVAR_ALIGN)) == NULL) { + alloc_failed_exception.isa = [OFAllocFailedException class]; + @throw (OFAllocFailedException*)&alloc_failed_exception; + } ((struct pre_ivar*)instance)->memchunks = NULL; ((struct pre_ivar*)instance)->memchunks_size = 0; ((struct pre_ivar*)instance)->retain_count = 1;