Index: buildsys.mk.in ================================================================== --- buildsys.mk.in +++ buildsys.mk.in @@ -99,13 +99,25 @@ regen=0; \ deps=""; \ test -f .deps || regen=1; \ for i in ${SRCS}; do \ case $$i in \ - *.o) \ + *.c) \ + test $$i -nt .deps && regen=1; \ + deps="$$deps $${i%.c}.dep"; \ + ;; \ + *.cc) \ + test $$i -nt .deps && regen=1; \ + deps="$$deps $${i%.cc}.dep"; \ + ;; \ + *.cxx) \ + test $$i -nt .deps && regen=1; \ + deps="$$deps $${i%.cxx}.dep"; \ + ;; \ + *.m) \ test $$i -nt .deps && regen=1; \ - deps="$${deps%.o}.dep $$i"; \ + deps="$$deps $${i%.m}.dep"; \ ;; \ esac; \ done; \ if test x"$$regen" = x"1" -a x"$$deps" != "x"; then \ ${DEPEND_STATUS}; \ Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -2,19 +2,21 @@ LIB_MAJOR = 1 LIB_MINOR = 0 SRCS = OFConstString.m \ OFConstWideString.m \ + OFException.m \ OFList.m \ OFListObject.m \ OFObject.m \ OFString.m \ OFWideString.m -OBJCFLAGS += -fPIC -DPIC -fno-nil-recivers -fconstant-string-class=OFConstString +OBJCFLAGS += -fPIC -DPIC -fno-nil-recivers -fconstant-string-class=OFConstString -fobjc-exceptions INCLUDES = OFConstString.h \ OFConstWideString.h \ + OFException.h \ OFList.h \ OFListObject.h \ OFObject.h \ OFString.h \ OFWideString.h ADDED src/OFException.h Index: src/OFException.h ================================================================== --- src/OFException.h +++ src/OFException.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2008 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of libobjfw. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE included in + * the packaging of this file. + */ + +#define __NO_OFEXCEPTION +#import "OFObject.h" + +@interface OFException: OFObject +@end ADDED src/OFException.m Index: src/OFException.m ================================================================== --- src/OFException.m +++ src/OFException.m @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2008 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of libobjfw. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE included in + * the packaging of this file. + */ + +#import "OFException.h" + +@implementation OFException +@end Index: src/OFObject.h ================================================================== --- src/OFObject.h +++ src/OFObject.h @@ -27,5 +27,16 @@ - (void*)resizeMem: (void*)ptr toSize: (size_t)size; - (void)freeMem: (void*)ptr; - free; @end + +#ifndef __NO_OFEXCEPTION +#import "OFException.h" + +@interface OFMemNotPartOfObjException: OFException ++ new: (void*)p + fromObject: (id)obj; +- init: (void*)p + fromObject: (id)obj; +@end +#endif Index: src/OFObject.m ================================================================== --- src/OFObject.m +++ src/OFObject.m @@ -58,36 +58,35 @@ iter->ptr = ptr; return ptr; } } - fprintf(stderr, "WARNING: Memory at %p was not allocated as part of " - "object %s!\n-> Memory was not resized!\n", ptr, [self name]); - + @throw [OFMemNotPartOfObjException new: ptr fromObject: self]; return NULL; } - (void)freeMem: (void*)ptr; { struct __ofobject_allocated_mem *iter; for (iter = __mem_pool; iter != NULL; iter = iter->prev) { if (iter->ptr == ptr) { - if (iter->prev != NULL) + if (iter->prev != NULL) iter->prev->next = iter->next; if (iter->next != NULL) iter->next->prev = iter->prev; + if (__mem_pool == iter) + __mem_pool = NULL; free(iter); free(ptr); return; } } - fprintf(stderr, "WARNING: Memory at %p was not allocated as part of " - "object %s!\n-> Memory was not free'd!\n", ptr, [self name]); + @throw [OFMemNotPartOfObjException new: ptr fromObject: self]; } - free { struct __ofobject_allocated_mem *iter, *iter2; @@ -99,5 +98,24 @@ } return [super free]; } @end + +@implementation OFMemNotPartOfObjException ++ new: (void*)ptr fromObject: (id)obj +{ + return [[OFMemNotPartOfObjException alloc] init: ptr + fromObject: obj]; +} + +- init: (void*)ptr fromObject: (id)obj +{ + fprintf(stderr, "ERROR: Memory at %p was not allocated as part of " + "object %s!\n" + "ERROR: -> Not changing memory allocation!\n" + "ERROR: (Hint: It is possible that you tried to free the same " + "memory twice!)\n", ptr, [obj name]); + + return [super init]; +} +@end Index: tests/Makefile ================================================================== --- tests/Makefile +++ tests/Makefile @@ -1,3 +1,3 @@ -SUBDIRS = OFString OFList OFWideString +SUBDIRS = OFObject OFString OFList OFWideString include ../buildsys.mk ADDED tests/OFObject/Makefile Index: tests/OFObject/Makefile ================================================================== --- tests/OFObject/Makefile +++ tests/OFObject/Makefile @@ -0,0 +1,7 @@ +PROG_NOINST = ofobject +SRCS = OFObject.m + +include ../../buildsys.mk + +CPPFLAGS += -I../../src +LIBS += -lobjc -L../../src -lobjfw ADDED tests/OFObject/OFObject.m Index: tests/OFObject/OFObject.m ================================================================== --- tests/OFObject/OFObject.m +++ tests/OFObject/OFObject.m @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2008 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of libobjfw. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE included in + * the packaging of this file. + */ + +#import +#import +#import + +#import "OFObject.h" + +int +main() +{ + OFObject *obj = [OFObject new]; + bool caught; + void *p, *q, *r; + + /* Test freeing memory not allocated by obj */ + puts("Freeing memory not allocated by object (should throw an " + "exception)..."); + caught = false; + @try { + [obj freeMem: (void*)123]; + } @catch (OFMemNotPartOfObjException *e) { + caught = true; + puts("CAUGHT! Resuming..."); + } + if (!caught) { + puts("NOT CAUGHT!"); + return 1; + } + + /* Test allocating memory */ + puts("Allocating memory through object..."); + p = [obj getMem: 4096]; + puts("Allocated 4096 bytes."); + + /* Test freeing the just allocated memory */ + puts("Freeing just allocated memory..."); + [obj freeMem: p]; + puts("Free'd."); + + /* It shouldn't be recognized as part of our obj anymore */ + puts("Trying to free it again (should throw an exception)..."); + caught = false; + @try { + [obj freeMem: p]; + } @catch (OFMemNotPartOfObjException *e) { + caught = true; + puts("CAUGHT! Resuming..."); + } + if (!caught) { + puts("NOT CAUGHT!"); + return 1; + } + + /* Test multiple memory chunks */ + puts("Allocating 3 chunks of memory..."); + p = [obj getMem: 4096]; + q = [obj getMem: 4096]; + r = [obj getMem: 4096]; + puts("Allocated 3 * 4096 bytes."); + + /* Free them */ + puts("Now freeing them..."); + [obj freeMem: p]; + [obj freeMem: q]; + [obj freeMem: r]; + puts("Freed them all."); + + /* Try to free again */ + puts("Now trying to free them again..."); + caught = false; + @try { + [obj freeMem: p]; + } @catch (OFMemNotPartOfObjException *e) { + caught = true; + puts("CAUGHT! Resuming..."); + } + if (!caught) { + puts("NOT CAUGHT!"); + return 1; + } + caught = false; + @try { + [obj freeMem: q]; + } @catch (OFMemNotPartOfObjException *e) { + caught = true; + puts("CAUGHT! Resuming..."); + } + if (!caught) { + puts("NOT CAUGHT!"); + return 1; + } + caught = false; + @try { + [obj freeMem: r]; + } @catch (OFMemNotPartOfObjException *e) { + caught = true; + puts("CAUGHT! Resuming..."); + } + if (!caught) { + puts("NOT CAUGHT!"); + return 1; + } + puts("Got all 3!"); + + /* TODO: Test if freeing object frees all memory */ + + return 0; +}