This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Understanding reference counting with Cocoa and Objective-C
I'm little confused with memory leaking - when I have to release object, and when it will be released automatically in iOS, so please help me understood using following code.
I have one method with following while block:
-(void) oneMethod {
NSMutableArray *returnValue = [[[NSMutableArray alloc] init] autorelease];
while(true) {
...
MyObject *myObj = [[MyObject alloc] initWithFrequency:100];
[returnValue addObject:myObj];
[myObj release];
...
}
}
Do I have to call [myObj release] or it will be released automatically in each loop?
Also, do I have to put autorelease in NSMutableArray init call, or it will be automatically released immediately after I return from method?
Thank you!
You should be using ARC - Automatic Reference Counting then you won't need to worry about releasing your allocated objects.
Your code is correct.
I find that as you work more with it you will get used to it. I don't spend much time thinking about it.
Generally, you need to release everything (or autorelease) you make.
Your loop is coded correctly in that its easy on memory, even for large arrays.
The sooner, the better is what I learned. Your example is appropriately releasing each myObj variable once inserted into the array. The array now "owns" the object and the object will exist as long as the array exists, no reason for the variable reference to remain.
ARC does seem to make all this completely unnecessary. I wonder how many developers will even learn this concept in the near future as ARC does it all for you now.
Presumably, you are not using ARC and so, if you did not call [myObj release] it would result in a leak each time through the loop.
Related
This might be a stupid question, but it keeps bothering me.
Say if we have a method that takes an NSString object as its parameter and does something with the NSString object,
- (void)someMethod:(NSString *)str
{
//do something with str
}
Consider this code
[someObject someMethod:[[NSString alloc] initWithFormat:#"Hello World!"]];
Since alloc has been used in creating the string as parameter of someMethod, it has to be balanced by release no matter explicitly in pre-ARC environment or implicitly under ARC. But it seems there is no way we can get a pointer to the string as we have never assigned it to any pointer.
So my question is, first, is this way of passing parameter prohibited in writing objective c code? If no, then how objects created this way get released? And finally, does this code lead to memory leak?
Just for the record, I understand the above code is written
NSString *string = [[NSString alloc] initWithFormat:#"Hello World!"];
[someObject someMethod:string];
// [string release]; depending on ARC or non-ARC
Well, in fact, that object is assigned to the variable named str, which is a parameter of your method. You can manage the memory inside your method via that pointer, although methods aren't supposed to take ownership of their arguments (except see below).
ARC knows what to do in this situation -- it will either autorelease the object or add a release once the method is finished.
Under MRR, your snippet would be a leak; the correct way to avoid that is also to send autorelease:
[someObject someMethod:[[[NSString alloc] initWithFormat:#"Hello World!"] autorelease]];
or to use your last snippet (putting the string into a temporary variable and releasing later).
As a slightly esoteric option, it is possible for your method to declare that it owns the argument, by using the ns_consumed attribute:
- (void)someMethod:(NSString *) __attribute__((ns_consumed)) str;
This indicates that your method should send release to the object before it returns -- ARC will also take care of that.
So my question is, first, is this way of passing parameter prohibited in writing objective c code?
No. It's perfectly legal.
If no, then how objects created this way get released?
ARC will take care of it for you. If you do your own reference counting, then you can add it to the autorelease pool before it goes out of scope:
[someObject someMethod:
[[[NSString alloc] initWithFormat:#"Hello World!"] autorelease]];
^^^^^^^^^^^
And finally, does this code lead to memory leak?
Not in ARC. In MRC, you would need to add the -autorelease.
The static analyzer would also point out that leak.
There's no reason to not write code as you ask for consideration on… nothing prohibited in the slightest. These objects get released in the same manner that any other object gets released. Your lack of a variable to store the pointer in at the top level isn't important because the Objective C runtime knows about the object.
I might've jumped into Objective-C a little too fast and assumed I knew enough about memory management to dive in. Turns out I wasn't.
Fast forward a bit and I've caught up ... for the most part. One of my last remaining questions regards the #property/#synthesize process and setting those values properly.
I've often seen this:
SomeObject *obj = [[SomeObject alloc] init];
self.obj = obj;
[obj release];
It makes sense, but I wonder if this accomplishes a similar enough thing to be an alternative:
self.obj = [[[SomeObject alloc] init] autorelease];
Would that be acceptable anywhere you might set the value of the #property, obj? Or is direct access to the instance variable preferred over both of those in the init method?
obj = [[SomeObject alloc] init];
Thanks.
EDIT: Definitely related question that discusses half of my question. The autorelease part of my question is referenced in one of the answers, but has not been confirmed.
So my questions still remain:
Is autorelease a valid alternative in this situation?
Can autorelease be used this way in the init method, or should the instance variable always be set directly in the init method?
The only difference is that in your first example, obj is released immediately (although it was presumably retained by the self.obj setter). The two examples are effectively the same.
Note that going forward, we can rely on ARC to deal with releasing objects at the appropriate time, so you can write:
self.obj = [[SomeObject alloc] init];
and let ARC worry about where to put the release or autorelease.
Update: You seem to be asking how things are different inside an -init method. The two things you need to be aware of are:
When possible, you should access ivars directly in -init and -dealloc methods. The idea is to avoid problems that could occur if your accessors are overridden by a subclass. There are a number of other questions here on SO that address this in greater depth, such as:
Why shouldn't I use Objective C 2.0 accessors in init/dealloc?
If you're creating an object in an -init method and assigning it to an ivar, you probably don't want to release it until a later point, such as -dealloc. So yes, it's fine in an -init method to not release the objects you create (so long as you keep a reference to them), but you'll still balance that +alloc with a -release in -dealloc.
I have a method of an object which creates objects which are then passed to a method of another object in another thread, like this:
MyClass* myClass = [[MyClass alloc] init];
[anotherClass performSelectorOnMainThread:#selector(method) withObject:myClass waitUntilDone:NO];
in method, I immediately retain the object, supposing it will be somehow released by the creator. My question is: how do I make MyClass release that object correctly? Is this the correct way to go?
My solution was to release the object manually in method. I see anyway that the Leak analyzer still recognizes this as a leak and seems it is not what Apple recommends, as the owner has the responsability to release the object.
Can you explain me the correct way to handle this situation? Thanks!
I don't fully understand what you're trying to achieve, but in general:
You shouldn't worry about who and when releases/deallocates the object. Instead, just make sure to retain it when you (a single object or method of yours) start needing it and release it when you stop needing it (or autorelease it, in which case it will be released on the thread on which you called autorelease).
This is exactly the way the performSelectorOnMainThread:withObject:waitUntilDone: works. From the documentation:
This method retains the receiver and the arg parameter until after the selector is performed.
It retains them while it needs them for doing it's job.
In short, the mehod that creates the objects and sends them to another thread should be:
MyClass* myClass = [[MyClass alloc] init]; // retained, will need it for performSelector
[anotherClass performSelectorOnMainThread:#selector(method) withObject:myClass waitUntilDone:NO];
[myClass release]; // no longer needing it.
or
MyClass* myClass = [[[MyClass alloc] init] autorelease]; // will be released automatically, but guaranteed to be retained until this method returns
[anotherClass performSelectorOnMainThread:#selector(method) withObject:myClass waitUntilDone:NO];
The way you have it now is a memory leak.
The receiving method:
if it uses the object only internally, doesn't have to retain it, since performSelector does "until after it is performed" (the method returns).
if it needs it later, it should be assigned to a property which retains it.
Your question is very hard to understand because you talk about this object, that object, another object and use meaningless names like myClass, anotherClass and method. It remains unclear which object you intend to release and which one is reported as leaking.
Anyhow, multi-threading doesn't add any special complexity to reference counting. Certainly, your two object myClass and anotherClass aren't short-lived objects. So if you use autorelease, make sure that the reference counter doesn't go to 0 if all autoreleases have been executed.
It's perfectly okay to release either myClass or anotherClass or both in method.
You don't show a lot of code. But what you show is okay.
I'm having a recurring problem in Objective-C. I'm either releasing things too many time, or not enough. or perhaps I'm not retaining them enough...
Can someone point me at a good reference that will give me a rule of thumb on when I need to retain and release?
For example:
I remember reading somewhere that some objects come pre-retained, so I need to release them, but not retain them. Which objects are these?
if I alloc an object and only need it in that method, do I need to release it? retain it?
Obviously, if I retained something, I needtorelease it, but beyond that, I get a bit lost.
The rules are generally pretty simple. If you get an object in one of the following ways:
id obj = [[MyObject alloc] init];
id obj = [myObject retain];
id obj = [myObject copy];
id obj = [myObject mutableCopy];
then you need to release it at some point -- in the same method, or your dealloc method, generally. In other words, balance your calls to alloc, retain, copy, and mutableCopy with a matching release call.
I remember reading somewhere that some objects come pre-retained, so I need to release them, but not retain them. Which objects are these?
This happens rarely. The documentation for the called method should specify that you are responsible for releasing the returned object; otherwise, you should assume you're receiving an autoreleased object.
if I alloc an object and only need it in that method, do I need to release it? retain it?
Yes, you need to release it (but you don't need to retain it). (You can also use one of the convenience methods that return an autoreleased object if you're only going to use it in that method.)
There is one and only one canonical reference: Apple's Memory Management Guide for Cocoa or iPhone.
Here is the gist of some code I'm writing. I'm concerned that I am not properly addressing the retain/release issues with the array class method on NSMutableArray. Is the following actually leaking memory?
for(a while) {
// do stuff
NSMutableArray *a = nil;
// do stuff
if (!a) {
a = [NSMutableArray array];
}
} // for(a while)
You wouldn't leak memory in this code, and releasing the array yourself will cause a crash when the array is autoreleased at the end of the run loop.
Most Cocoa classes provide a couple of ways of making a new object, and are very consistent with this convention:
[[NSSomeObject alloc] init] : you are responsible for releasing the object (instance method).
[NSSomeObject someObject] : the object will be autoreleased for you, usually at the end of the run loop (class method). It's roughly equivalent to [[[NSSomeObject alloc] init] autorelease].
The proper use of the instance method would be:
a = [[NSMutableArray alloc] init];
// do stuff
[a release];
The proper use of the class method would be:
a = [NSMutableArray array];
// do stuff, array is in the autorelease pool
Note that Apple has recommended you stay away from the convenience methods as much as possible to improve performance. This is controversial advice, may not save much processor time, and separates the alloc-init from the release on an object you may not actually care much about keeping.
From the Cocoa Memory Managment Rules:
You take ownership of an object if you create it using a method whose name begins with “alloc” or “new” or contains “copy” (for example, alloc, newObject, or mutableCopy), or if you send it a retain message. You are responsible for relinquishing ownership of objects you own using release or autorelease. Any other time you receive an object, you must not release it.
Therefore with the line:
a = [NSMutableArray array];
you do not take ownership of the array, and it will be passed to you autoreleased. The memory will be handled for you automatically by the autorelease pool, and once it is no longer being used, it will be released for you. If you want to keep the array outside the current event, however, you must retain it, otherwise it will be released for you.
Yes, if you want it to stick around.
The returned object is an autoreleased object which will get deallocated when its autorelease pool gets purged.
All the array class methods that begin with "array" return these types of autoreleased objects.
Read this doc by Apple.
That's valid. It may help to just manage things manually when you have questions, to learn.
There is a convention:
init prefixes (init, initWithString:) indicate a retain count of 1, where
objectname prefixes (string, stringWithString:) indicates an autoreleased object
I have had the habit, for years, to release what I can at the call site, rather than pushing it to be autoreleased. Some autorelease issues then become painfully difficult to track down. Sure, autorelease is a convenience to the programmer in this case (provided nothing goes wrong), but adversely affects reuse, clarity, and performance (moreso in large codebases/programs).