views:

332

answers:

5

Hello ! every one.

I have a little query regarding the memory management.

Let's begin with an example. Assume we have a class as follows.

@interface myClass : NSObject {
    NSString *xyz;
}
@end

Now, see the implementation.

@interface myClass : NSObject {
    NSString *xyz;
}
@end

@implementation myClass
-(void)abc{
    // xyz allocted here
}
-(void)pqr{
    // retained or copied many times or may not a single time
}
-(void)mno{
    // retained or copied many times or may not a single time
}
-(void)jpg{
    // may be released more than one time or may be not
}


//-(void)dealloc{
//  [xyz release];
//  [super dealloc];
//}
//
//-(void)dealloc{
//  if(xyz!=nil && [xyz retainCount]>0){ [xyz release]; xyz=nil; }
//  [super dealloc];
//}

-(void)dealloc{
    if(xyz!=nil){ 
        while([xyz retainCount]>0) 
           [xyz release]; 
        xyz=nil; 
    }
    [super dealloc];
}
@end

In above code. I have three dealloc functions. Which one is preferable? If none of these, then please suggest yours. I am confused, just because - "Objective c" says, object must be released each time = each time alloc/retained.

But most of the sample code has just single statement "[xyz release];" doen't it create memory leak?

Thanks in advance for your explanation.

Sagar

A: 
    while([xyz retainCount]==0) 
       [xyz release]; 

Should be > 0, otherwise the -release is not executed. Even so, deallocating xyz like this is a bad practice because xyz may be still owned by someone else.

You should allocate xyz one and only one time, and if you -copy it to replace xyz, always -release the old one. Always follow the Cocoa memory management rule.

If you really need to adopt multiple ownership to xyz, and a separate integer ivar to record how many times you have retained xyz, so you have the correct number to -release in -dealloc.

KennyTM
+4  A: 
- (void)dealloc {
    [xyz release];
    [super dealloc];
}

...is the correct version. In Objective-C, you generally shouldn't use the retainCount method.

If you want to be very safe, you can also write:

- (void)dealloc {
    [xyz release], xyz = nil;
    [super dealloc];
}
Steve Harrison
sugar
This is only partly correct. You also need `[super dealloc];` in there.
Dave DeLong
@Dave DeLong: I just realised that!
Steve Harrison
@Steve then +1 ;)
Dave DeLong
@Dave DeLong: Thank you! :)
Steve Harrison
+1  A: 

The idea is that myClass has a member variable (in your case, xyz). When a myClass object gets created, it should create (or get a reference to) xyz by adding only 1 to the retain count (whether through retain or other means depends on the situation).

It would not be a good idea in each method to retain xyz with releasing it again. So at the end of each method, the the local object should have no more holds on xyz than it had at the beginning of the method.

By the time dealloc gets called, only that single retain hold should remain on xyz (as far as the myClass object is concerned), so a single call to release will suffice. It is not a good idea to release until the retainCount is zero because another object somewhere might be using it.

To directly answer your question, use this dealloc:

-(void)dealloc{
    [xyz release];
}
Aaron
suppose I have written statements like - [xyz retain]; [xyz retain]; [xyz retain]; [xyz retain]; [xyz retain]; [xyz retain]; then what???
sugar
@sagar: You should have `release`d `xyz` at appropriate points before `dealloc`.
Steve Harrison
Then you should release it 6 times as well. But if you're writing code like that, you CLEARLY do not understand what retain and release mean. You should never… ever… Ever write code like that. Ever.
BJ Homer
+1  A: 

objects those are retained during the poperty declaration need to be released in the dealloc method. So if you are declaring

@property(nonatomic, retain)NSString xyz;,

you need it to be released in dealloc as

-(void)dealloc{
    [xyz release];
    [super dealloc]
}

Any other allocated memory should be released immediately after the last use of that object from within your methods.

So if you are allocating xyz, in

-(void)abc{
    // xyz allocted here
}

then you shoud release it at the end of the same method.

-(void)abc{
    // xyz allocted here
// do something with xyz

//release xyz

example:

        -(void)abc{
           xyz=[[NSString alloc]init];//this may not be what you are following, but i just meant allocating memory
        // do something with xyz


    [xyz release]  

  //release xyz

In this case you need not release it in the dealloc method.

Also not that if you are property declaring xyz and retining it, you should not allocate it in your methods nor should release

Nithin
Don't forget your pointer! ;)
Reed Olsen
If you're allocating and deallocating in the same method, xyz should be declared at the local scope, not at the class scope.
Duncan
i also meant the same thing, those given above are 2 possible methods, if you are declaring it as a class scope, it is to be released in the dealloc method and if declared as local scope, release there itself. Thats why i noted in the end that, one should use either of these methods, either local or class scope, not both at a time
Nithin
+11  A: 

This is absolutely wrong:

while([xyz retainCount]>0) 
       [xyz release]; 
    xyz=nil; 

retainCount will never return 0, because as soon as you are at a retainCount of 1 and the object is released, the runtime just deallocates it right then and there, never decrementing the retainCount. Even if it did decrement the retainCount, the object is now deallocated. How are you going to ask it what it's retainCount is?

In a nutshell, your design is wrong. If you can't keep track of how often you've retained an object in a smarter way, then you will have memory leaks and most likely crashes from overreleasing objects (this while loop will crash your app).

If you absolutely can't change your code (I wouldn't believe you if you said you couldn't), then you'd want to keep a second integer ivar indicating how many times you've retained xyz, and then use that to figure out how many times you should release it. (However, this should be an absolute last ditch effort, as in Armaggeddon will happen if you don't get this working in 30 seconds. You should really refactor your code first.)

In addition, you've forgotten the call to [super dealloc] in your dealloc method.

Dave DeLong
But you didn't include the exact answer according to you??
sugar
@sagar the exact answer is that you only need to retain `xyz` once, which means you only need to release it once.
Dave DeLong