//自己生成并持有对象
id obj = [[NSObject alloc] init];
//自己持有对象
[obj release];
//对象已释放
[obj release];
//释放之后再次释放已非自己持有的对象,应用程序崩溃。
//崩溃情况: 再度废弃已经废弃了的对象时崩溃, 访问已经废弃的对象时崩溃
我们取得对象,但是自己不持有对象:
//取得对象,但是自己并不持有对象
id obj1 = [obj0 object];
//释放不是自己持有的对象,应用程序崩溃
[obj1 release];
/**
* Allocates a new instance of the receiver from the default
* zone, by invoking +allocWithZone: with
* NSDefaultMallocZone()
as the zone argument.
* Returns the created instance.
*/
+ (id) alloc
{
return [self allocWithZone: NSDefaultMallocZone()];
}
*
* If you have turned on debugging of object allocation (by
* calling the GSDebugAllocationActive
* function), this method will also update the various
* debugging counts and monitors of allocated objects, which
* you can access using the GSDebugAllocation...
* functions.
*
*/
+ (id) allocWithZone: (NSZone*)z
{
return NSAllocateObject (self, 0, z);
}
/*
* Now do the REAL version - using the other version to determine
* what padding (if any) is required to get the alignment of the
* structure correct.
*/
struct obj_layout {
char padding[__BIGGEST_ALIGNMENT__ - ((UNP % __BIGGEST_ALIGNMENT__)
? (UNP % __BIGGEST_ALIGNMENT__) : __BIGGEST_ALIGNMENT__)];
NSUInteger retained;
};
inline id
NSAllocateObject (Class aClass, NSUInteger extraBytes, NSZone *zone) {
int size = 计算容纳对象所需内存大小.
id new = NSZoneMalloc(zone, size);
memset(new, 0, size);
new = (id) & ((struct obj_layout *)new)[1];
}
struct obj_layout {
NSUInteger retained;
};
+ (id) alloc {
int size = sizeof (struct obj_layout) + 对象大小;
struct obj_layout *p = (struct obj_alyout*)calloc(1, size);
return (id)(p + 1);
}
/**
* Returns the reference count for the receiver. Each instance has an
* implicit reference count of 1, and has an 'extra reference count'
* returned by the NSExtraRefCount() function, so the value returned by
* this method is always greater than zero.
* By convention, objects which should (or can) never be deallocated
* return the maximum unsigned integer value.
*/
- (NSUInteger) retainCount
{
#if GS_WITH_GC
return UINT_MAX;
#else
return NSExtraRefCount(self) + 1;
#endif
}
/**
* Return the extra reference count of anObject (a value in the range
* from 0 to the maximum unsigned integer value minus one).
* The retain count for an object is this value plus one.
*/
inline NSUInteger
NSExtraRefCount(id anObject)
{
#ifdef __OBJC_GC__
if (objc_collecting_enabled())
{
return UINT_MAX-1;
}
#endif
#if GS_WITH_GC
return UINT_MAX - 1;
#else /* GS_WITH_GC */
return ((obj)anObject)[-1].retained;
#endif /* GS_WITH_GC */
}
retain方法:
/**
* Increments the reference count and returns the receiver.
* The default implementation does this by calling NSIncrementExtraRefCount()
*/
- (id) retain
{
#if (GS_WITH_GC == 0)
NSIncrementExtraRefCount(self);
#endif
return self;
}
/**
* Increments the extra reference count for anObject.
* The GNUstep version raises an exception if the reference count
* would be incremented to too large a value.
* This is used by the [NSObject-retain] method.
*/
inline void
NSIncrementExtraRefCount(id anObject)
#endif
{
#if GS_WITH_GC || __OBJC_GC__
return;
#else /* GS_WITH_GC */
if (allocationLock != 0)
{
#if defined(GSATOMICREAD)
/* I've seen comments saying that some platforms only support up to
* 24 bits in atomic locking, so raise an exception if we try to
* go beyond 0xfffffe.
*/
if (GSAtomicIncrement((gsatomic_t)&(((obj)anObject)[-1].retained))
> 0xfffffe)
{
[NSException raise: NSInternalInconsistencyException
format: @"NSIncrementExtraRefCount() asked to increment too far"];
}
#else /* GSATOMICREAD */
NSLock *theLock = GSAllocationLockForObject(anObject);
[theLock lock];
if (((obj)anObject)[-1].retained == UINT_MAX - 1)
{
[theLock unlock];
[NSException raise: NSInternalInconsistencyException
format: @"NSIncrementExtraRefCount() asked to increment too far"];
}
((obj)anObject)[-1].retained++;
[theLock unlock];
#endif /* GSATOMICREAD */
}
else
{
if (((obj)anObject)[-1].retained == UINT_MAX - 1)
{
[NSException raise: NSInternalInconsistencyException
format: @"NSIncrementExtraRefCount() asked to increment too far"];
}
((obj)anObject)[-1].retained++;
}
#endif /* GS_WITH_GC */
}
/**
* Decrements the retain count for the receiver if greater than zero,
* otherwise calls the dealloc method instead.
* The default implementation calls the NSDecrementExtraRefCountWasZero()
* function to test the extra reference count for the receiver (and
* decrement it if non-zero) - if the extra reference count is zero then
* the retain count is one, and the dealloc method is called.
* In GNUstep, the [NSObject+enableDoubleReleaseCheck:] method may be used
* to turn on checking for ratain/release errors in this method.
*/
- (oneway void) release
{
#if (GS_WITH_GC == 0)
if (NSDecrementExtraRefCountWasZero(self))
{
# ifdef OBJC_CAP_ARC
objc_delete_weak_refs(self);
# endif
[self dealloc];
}
#endif
}
BOOL NSDecrementExtraRefCountWasZero(id anObject) {
if (((struct obj_layout *)anObject)[-1].retained == 0) {
return YES;
} else {
((struct obj_layout *)anObject)[-1].retained--;
return NO;
}
}
*
* If you have allocated the memory using a non-standard mechanism, you
* will not call the superclass (NSObject) implementation of the method
* as you will need to handle the deallocation specially.
* In some circumstances, an object may wish to prevent itself from
* being deallocated, it can do this simply be refraining from calling
* the superclass implementation.
*
*/
- (void) dealloc
{
NSDeallocateObject (self);
}
inline void NSDeallocateObject(id anObject) {
struct obj_layout *o = &((struct obj_layout*)anObject)[-1];
free(o);
}
int __CFDoExternRefOperation(uintptr_t op, id obj) {
CFBasicHashRef table = init;
int count;
switch (op) {
case OPERATION_retainCount;
count = CFBasicHashGetCountOfKey(table, obj);
return count;
case OPERATION_retain:
CFBasicHashAddValue(table, obj);
return obj;
case OPERATION_release:
count = CFBasicHashRemoveValue(table, obj);
return 0 == count;
}
}
- (NSUInteger)retainCount {
return (NSUInteger) __CFDoExternRefOperation(OPERATION_retainCount, self);
}
- (id)retain {
return (id)__CFDoExternRefOperation(OPERATION_retain, self);
}
- (void)release {
return __CFDoExternRefOperation(OPERATION_release, self);
}
for (int i = 0; i < count; ++i) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
***
[pool drain];
}
- (id) autorelease {
[NSAutoreleasePool addObject:self];
}
class AutoreleasePoolPage {
static inline void *push() {
生成或持有NSAutoreleasePool类对象。
}
static inline void *pop(void *token) {
废弃NSAutoreleasePool类对象;
releaseAll();
}
static inline id autorelease(id obj) {
相当于NSAutoreleasePool类的addObject类方法。
}
id *add(id obj) {
追加;
}
void releaseAll() {
调用内部数组中的对象的release实例方法。
}
}
void *objc_autoreleasePoolPush(void) {
return AutoreleasePoolPage::push();
}
void objc_autoreleasePoolPop(void *ctxt) {
AutoreleasePoolPage:pop(ctxt);
}
id *obj_autorelease( id obj) {
return AutoreleasePoolPage::autorelease(obj);
}
id autorelease_class [NSAutoreleasePool class];
SEL autorelease_sel = @selector(addObject:);
IMP autorelease_imp = [autorelease_class methodForSelector:autorelease_sel];
实际:
- (id)autorelease {
(*autorelease_imp)(autorelease_class, autorelease_sel, self);
}
与
- (id)autorelease {
[NSAutoreleasePool addObject:self];
}