Re: releasing NSProgressIndicator
Re: releasing NSProgressIndicator
- Subject: Re: releasing NSProgressIndicator
- From: "Oscar Bascara" <email@hidden>
- Date: Wed, 23 May 2007 08:32:15 -0700
On 5/23/07, Uli Kusterer <email@hidden> wrote:
On 23.05.2007, at 08:39, Oscar Bascara wrote:
> NSProgressIndicator *progressIndicator = [[[NSProgressIndicator alloc]
> initWithFrame:frameRect] autorelease];
You're calling autorelease here, so it gets released when the
current pool goes out of scope.
> [progressIndicator setStyle:NSProgressIndicatorSpinningStyle];
> [view addSubview:progressIndicator];
addSubview retains your object once.
> [progressIndicator startAnimation:self];
>
> To destroy:
>
> [progressIndicator stopAnimation:self];
> [progressIndicator removeFromSuperview];
removeFromSuperview balances the retain addSubview did, by calling
release or autorelease once.
> Oddly, if I create a second NSProgressIndicator object as above, the
> first object suddenly does get released. This appears to happen
> directly after the animationStart. Could it be that the first object
> was being retained in an animation thread and then got released when
> the second object needed to animate?
I've never heard of something like that. But you are balancing your
retains/releases here, so that should work just fine. You shouldn't
have to care about whether the retainCount is still 1 after you call
removeFromSuperview. The whole point of retain/release is not having
to care who else needs the object you created. Maybe the animation
thread is still running, and won't be releasing its hold over the
indicator until the run loop (main event loop) has regained control
and given it some more processing time to clean up. Or maybe
removeFromSuperview calls autorelease and at the time you check the
retainCount, the pool it's been added to hasn't been released yet.
Whatever it is, as long as you're not doing any unbalanced retains
you're not telling us about, you needn't care whether the retain
count takes a while to go to 0 or not.
If you're worried there may be a leak, subclass NSProgressIndicator
and override dealloc and initWithFrame: to NSLog() (in addition to
calling through to super), and then check whether both get called in
a balanced fashion. If they don't, override retain and release and
check for any code you are calling yourself that causes a retain.
However, don't just go willy-nilly adding release calls, because if
you over-release, the other code that did this retain that you're
balancing will expect the object is still there although it's long
gone. And if there was a bug in Cocoa that caused some object not to
be released, Apple would eventually fix it and if you called release
yourself to balance Apple's retain, you'd be over-releasing then, and
your app would blow up.
Thank you much for your detailed response. I'm glad that my
retains/releases are balance as I hoped, and I now feel more
comfortable against a memory leak.
At this point, I will definitely leave the code as it is. But here is
just a little more information. I had subclassed NSProgressIndicator
and overriden dealloc. And an NSProgressIndicator object does not get
deallocated, which made me worry about a memory leak, until (possibly
much later when) another object is created and starts animating.
Maybe there is also a thread leak?
Also, the retainCount for the sending object increases directly after
startAnimation. So part of the retain/release balance may have to
include startAnimation/stopAnimation. Note that commenting out
startAnimation and stopAnimation does lead to an NSProgressIndicator
dealloc right away.
Oscar
Memory bugs are very insiduous, as memory doesn't get cleared out
after an object got released, and memory gets reused. If you access
an object after it got released, the memory where it used to be may
still be looking like that object, and it might perform your method
calls just fine. However, if the memory that object used to own gets
reused, your "zombie object" may look perfectly valid, but overwrite
the reused memory. So, you may not notice you're making the mistake
where you're calling a zombie object, but that call may be clobbering
memory now used by some completely unrelated system function, which
will blow up in your face the next time you call it, which may be
hours later. That's much more dangerous than a leak that Apple will
fix in the next system update.
So, don't worry too much about retain counts. Autorelease is used a
lot, and the retain count doesn't go down while an autorelease is
still queued up. It will only go down when the pool goes away and
actually calls release. There's many accessors that do [[obj retain]
autorelease] to make sure the object stays available even if the next
thing you do is delete the owner of obj, so the retain count could be
50 when you've done all your releases, but will eventually go down to
0 as expected.
Cheers,
-- M. Uli Kusterer
http://www.zathras.de
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden