released object won't dealloc - ideas?
To simplify my situation, it's like this.
When my main code calls [Globals cleanup], I can verify that player gets released. However, the delloc method for the Player class is not getting called. There is no other place in my entire program that creates or retains the player object. It is only done in the Globals setup function, and I have verified by using NSLog messages that it is not being called more than once before the next cleanup.
Any thoughts and help are appreciated.
Code:
@interface Globals
{
Player *player;
}
Globals setup
{
player = [Player init retain]; //etc...
}
Globals cleanup
{
if (player)
{
[player release];
player = nil;
}
}When my main code calls [Globals cleanup], I can verify that player gets released. However, the delloc method for the Player class is not getting called. There is no other place in my entire program that creates or retains the player object. It is only done in the Globals setup function, and I have verified by using NSLog messages that it is not being called more than once before the next cleanup.
Any thoughts and help are appreciated.
Gillissie Wrote:To simplify my situation, it's like this.
Code:
@interface Globals
{
Player *player;
}
Globals setup
{
player = [Player init retain]; //etc...
}
Globals cleanup
{
if (player)
{
[player release];
player = nil;
}
}
When my main code calls [Globals cleanup], I can verify that player gets released. However, the delloc method for the Player class is not getting called. There is no other place in my entire program that creates or retains the player object. It is only done in the Globals setup function, and I have verified by using NSLog messages that it is not being called more than once before the next cleanup.
Any thoughts and help are appreciated.
If I'm reading your shorthand correctly, you're doing this:
Code:
[[[Player alloc] init] retain];Which is wrong. When you call alloc, the new object is allocated with a retain count of 1. Init does not change this. When you retain it again, its retain count is now 2.
If you don't retain it again, the problem should go away.
Consider re-reading Memory Management Programming Guide for Cocoa [developer.apple.com] again if you're unsure, and then try running the static analyser if you're using Clang - it can spot a lot of related reference counting errors.
Checking the value of [myObject retainCount] is often useful when you are having a problem like that.
Thanks for the replies. I swear I read that doing it this way didn't retain it, which is why you need to use autorelease if you wrap the alloc call in a convenience function. I'll check it out though.
[edit] I reviewed the doc. What I misunderstood is that if you return the new object without autorelease, then the reference pointer is lost but the object still exists in memory. That's messed up, but I get it now. I guess I better review all of my init code for all objects.
[edit] I reviewed the doc. What I misunderstood is that if you return the new object without autorelease, then the reference pointer is lost but the object still exists in memory. That's messed up, but I get it now. I guess I better review all of my init code for all objects.
I find a good pattern to follow is to always do
MyObj *obj=[[[MyObj alloc] init] autorelease];
for local variables - the autorelease ensures the object will get cleaned up when you return the run loop (or any enclosing release pool).
And do
self.obj=[[[MyObj alloc] init] autorelease];
with a matching
self.obj=nil;
in my dealloc/cleanup.
where obj is a property declared with the retain attribute.
There are several unnecessary releases, retains, autoreleases going on, but the code is consistent and it's very hard to make a mistake.
MyObj *obj=[[[MyObj alloc] init] autorelease];
for local variables - the autorelease ensures the object will get cleaned up when you return the run loop (or any enclosing release pool).
And do
self.obj=[[[MyObj alloc] init] autorelease];
with a matching
self.obj=nil;
in my dealloc/cleanup.
where obj is a property declared with the retain attribute.
There are several unnecessary releases, retains, autoreleases going on, but the code is consistent and it's very hard to make a mistake.
iamflimflam1 Wrote:I find a good pattern to follow is to always do
MyObj *obj=[[[MyObj alloc] init] autorelease];
for local variables - the autorelease ensures the object will get cleaned up when you return the run loop (or any enclosing release pool).
And do
self.obj=[[[MyObj alloc] init] autorelease];
with a matching
self.obj=nil;
in my dealloc/cleanup.
where obj is a property declared with the retain attribute.
There are several unnecessary releases, retains, autoreleases going on, but the code is consistent and it's very hard to make a mistake.
I read in the Cocoa Performance Guidelines [developer.apple.com] that it is a good idea to minimize your use of the autorelease pool system. I think they're indicating that this:
Code:
- (id)runOperation {
NSAutoreleasePool * pool0 = [[NSAutoreleasePool alloc] init];
BigScaryObject * foo = [[BigScaryObject alloc] init];
// do scary things
[foo release];
[pool0 release];
}is better than simply autoreleasing BigScaryObject up front.
In reality, I seriously doubt the performance difference will be at all important, though I think it's a good thing to know if you're ever writing some code that needs to or should execute very quickly (say, in a very tight loop) that needs to use Cocoa frameworks.
Another reason to minimize your autorelease is that autoreleased objects that cause a bug to happen are much harder to figure out because the function call won't come from your code but rather from apples code.
cmiller Wrote:I read in the Cocoa Performance Guidelines [developer.apple.com] that it is a good idea to minimize your use of the autorelease pool system. I think they're indicating that this:
Code:
- (id)runOperation {
NSAutoreleasePool * pool0 = [[NSAutoreleasePool alloc] init];
BigScaryObject * foo = [[BigScaryObject alloc] init];
// do scary things
[foo release];
[pool0 release];
}
is better than simply autoreleasing BigScaryObject up front.
In reality, I seriously doubt the performance difference will be at all important, though I think it's a good thing to know if you're ever writing some code that needs to or should execute very quickly (say, in a very tight loop) that needs to use Cocoa frameworks.
Mmmm... It's more like this...
Code:
{
loop a billion times {
NSSomething * blah = [NSSomething somethingEtc] (autoreleased)
.... do more allocations and things ....
}
}That'll just eat gobs of memory which:
- Is inefficient in that it uses gobs more than it needs to
- Can be slow because of the time to actually allocate new memory to the app
- Can be gargantuanly slow because you can cause page outs when you eat sooo much memory you have to steal RAM from other processes.
The performance guidelines are suggesting:
Code:
{
loop a billion times {
NSSomething * blah = [[NSSomething alloc] init]
.... do more allocations and things ....
[blah release];
}
}You don't really need to avoid autorelease in any circumstances other than ones where you allocate a huge number of objects and there's no autorelease pool keeping memory usage in check constantly.
FreakSoftware Wrote:Mmmm... It's more like this...
Code:
{
loop a billion times {
NSSomething * blah = [NSSomething somethingEtc] (autoreleased)
.... do more allocations and things ....
}
}
That'll just eat gobs of memory which:
- Is inefficient in that it uses gobs more than it needs to
- Can be slow because of the time to actually allocate new memory to the app
- Can be gargantuanly slow because you can cause page outs when you eat sooo much memory you have to steal RAM from other processes.
I've always called that a "tight loop." My jargon might be off though. Sorry to confuse!
But we're both saying the same thing, which is good.
Re-reading what your last few sentences, yeah, you mentioned the tight loops. I kinda skipped over that the first time I read it and just saw your code block without a loop.
Possibly Related Threads...
| Thread: | Author | Replies: | Views: | Last Post | |
| removeFromSuperview not calling dealloc of view - SOLVED | BeyondCloister | 5 | 9,530 |
Aug 11, 2010 01:18 PM Last Post: BeyondCloister |
|

