Re: retain, copy, release, autorelease...leak
Re: retain, copy, release, autorelease...leak
- Subject: Re: retain, copy, release, autorelease...leak
- From: Fritz Anderson <email@hidden>
- Date: Thu, 28 Jun 2001 15:20:37 -0500
At 11:12 AM -0700 6/28/2001, Richard Collyer wrote:
I have what seems like should be simple code, but depending on how I deal with
memory, I either crash with a SIGINT or have a memory leak.
His code, condensed:
- (id) init {
NSMutableArray *myArray;
int x, y;
NSColor *colorStore;
// IS THIS RETAIN REDUNDANT (I.E. BAD)?
myArray = [[NSMutableArray arrayWithCapacity: 10] retain];
You use a convenience allocator/initializer, instead of
alloc]init...; therefore myArray comes to you autoreleased. Its
retain count is 1, but it is scheduled to decrement (and, if at zero,
to release the object) in the next pass of the event loop. Therefore
the retain is GOOD.
The retain increments the retain count to 2, so when the autorelease
is resolved in the event loop, it still has a retain count of 1.
for (x = 0; x< 10000; ++x) {
colorStore = [self Quicky];
colorStore gets an NSColor that was created by
colorWithDeviceRed:green:blue:alpha:. This is a convenience method,
so the object has been autoreleased. It will go away when you hit
the event loop, unless you do something that retains it...
[myArray addObject: colorStore];
... like adding it to a collection object. The NS collections retain
objects upon adding them. No further retain necessary; colorStore's
retain count is 2, its autorelease count is 1, and it will survive
the next event loop with a retain count of 1.
}
for (y = 0; y < 100; ++y) {
for (x = 0; x< 10; ++x) {
colorStore = [self Quicky];
[myArray replaceObjectAtIndex: x withObject: colorStore];
For the objects that get added to the array from colorStore, the
story is the same as above: Quicky returns an autoreleased object,
the insertion into myArray adds a retain, and the object would
survive the next event loop.
Removing an object from a collection (by remove..., replace..., or
deallocation of the collection) releases the object. The objects
that had been in myArray when replace... was hit have their retain
counts decremented immediately.
Note well that in this simple method, objects are being added and
dropped from the array without control ever reaching the event loop.
They are therefore being restored to the state they had when returned
from Quicky: Retain count 1, autorelease count 1, will be
deallocated in the event loop.
//[colorStore release];
Don't do this. It takes colorStore from retain 2/autorelease 1 to
retain 1/autorelease 1. If you do this...
}
}
[myArray release];
... then this release will run through the array, releasing each
member -- setting it to retain 0/autorelease 1. The retain 0 means
that the object is immediately deallocated. The autorelease count
isn't a literal property of the object, but indicates that the
current autorelease pool still has the object's address in its
release queue. Control eventually reaches the event loop, where the
current pool is released, and the pool attempts to send release to
the object -- which, having been deallocated, causes a SIG.
self = [super init];
return self;
At this point, as init ends, there are a great number of objects in
the heap to which you have no reference. You can see them taking up
memory, and you might think they represent a leak. But they all have
one last reference, in the autorelease pool; they will be released,
and deallocated when the current pool is released.
}
-- F
--
Fritz Anderson <email@hidden>
Parallel Software, Inc <
http://www.parallel.com/>
Naperville, Illinois