I am getting another memory leak in a non-void instance method that returns a object of class NSMutableArray.
Can someone advise me on how I can fix this leak? I tried to release 'userFollowings' at the end of the method but it's still reporting a leak.
When your are to return an object from a method in which you have either initialized it or retained it, it is common practice to return it autoreleased. That way, the user receiving the object doesn't have to worry about releasing it. So, your final line of code should look like this:
return [userFollowing autorelease];
It probably wouldn't hurt to read a little from the Memory Management Programming Guide to catch up on memory management rules such as this, and there are plenty of other helpful resources out on the web and on this site.
There are a set of conventions used by Cocoa programs that make memory management much less error prone. When a method returns an object, the code that calls it needs to know if it owns it or not.
What it boils down to is that if you are writing a method that returns an object and that method doesn't convey ownership upon the caller by being named something like new, alloc, copy, etc., you need to autorelease it before you return it.
That's what the message you are getting is talking about - "Object returned to caller as an owning reference" means that you're conveying ownership on the calling code. The problem is that your method name indicates otherwise.
If I were to call your method and needed to hang onto the object, I'd call retain on it so that I owned it. I need to do this because your method name implied I wasn't the owner. So long as you are returning an autoreleased object, that's correct. But if you don't autorelease the object, it will end up with a retain count of 2 - once when you allocated it and once when I retained it. When I finally get round to releasing it, it will still have a retain count of 1, and will never be deallocated from memory, resulting in a memory leak.
The problem is that userFollowings never gets released. Try ending with
return [userFollowings autorelease];
Try this:
NSMutableArray* userfollwings = [[[NSMutableArray alloc] init] autorelease]
Related
If I do this-
SomeObject* someObject = [[SomeObject alloc] init];
[[someObject release] release];
I presume my program wouldn't crash because the second over-release is acting on nothing.
Whereas
[[someObject autorelease] autorelease];
would crash because the object is released twice by being passed down the chain.
This is a matter of curiousity only, I guess I've never had a problem with it so far.
(See this answer for an explanation what oneway does.)
Your first example doesn't even compile, as void != nil. But if you simply call release two times on an object that has a retain count of 1, it'll for sure crash.
As for why release returns void while autorelease returns id: The first says I don't need this object any more, you may get rid of it. Thus, if it would return something and you would operate on it you're likely to operate on a dead object. By contrast, autorelease more or less says "Soon I won't be needing the object any more but let it stick around until I'm done with the current method."
So as you see they are similar in that they say I won't be needing this object any more, but they differ in the time: release says "you can get rid of the object now", while autorelease says "you may get rid of the object later".
I suppose this is mainly done for ease of use, as one could of course do without (and put every autorelease on its own line):
Whenever you release an object, you're done with it (or at least you should be). There is no need to return the object as it may well have been destroyed already and in any case the caller should not work with the object if it is not yet destroyed (i.e. someone else has a reference to it).
On the other hand autorelease is often used in conjunction with init/alloc and just marks the object for later destruction. Whenever using autorelease one can almost be sure that the object is being used afterwards. Whether you directly return it or work with it on your own (e.g. after [[[SomeClass alloc] init] autorelease]) it is very handy to have the object returned as it saves an explicit line of code for autorelease. It is also helpful to have the autorelease directly in the same line: On return [someObject autorelease] you can directly see, that this is an autoreleased object. If you use it with init/alloc you can directly see that this object does not need another release.
I believe, you've answered your question yourself. Call to autorelease can be in the very beginning of object's life, so probably you'll need to save some code lines by the following statement:
[anotherObject callMethodWithArg: [myObject autorelease]];
Indeed, that's helpful. However, you call a release, in the very end of the code, that uses your object. By saying immediate release, you are saying you don't need this object here anymore. So there's no sense in reusing it's instance. Another option is, that a release call can actually deallocate the object immediately, so returning an invalid pointer will not be a good idea =)
I am trying to know about release keyword. I allocated it once, and then I released it. then also the message was passed to that object. And it gives me output. But the retain count is zero. What is the reason behind this?
MyClass *obj=[[MyClass alloc]init];
[obj release];
[obj WhoAreYou];
I given "NSLOG(#"It is the problem.");"
I got the out put: It is the problem.
See this link..a simple tutorial on memory management..It says
You can think of release as saying
relinquish ownership of this object,
rather than destroy this object
That means when you release you are just losing your control over the object..You are not releasing it..Cocoa will release the variable if it is not referenced by anyone else
I am still new to this Memory Management stuff (Garbage Collector took care of everything in Java), but as far as I understand if you allocate memory for an object then you have to release that memory back to the computer as soon as you are finished with your object.
myObject = [Object alloc];
and
[myObject release];
Right now I just have 3 parts in my Objective-C .m file: #Interface, #Implementation and main. I released my object at the end of the program next to these guys:
[pool drain];
return 0;
But what if this program were to be a lot more complicated, would it be okay to release myObject at the end of the program?
I guess a better question would be when do I release an object's allocated memory? How do I know where to place [myObject release];?
This is probably a little over-simplified, but in general, you are going to want to release it where you declared it.
If you declare an object INSIDE a particular method call, then by definition, you will be done with that object (or at least that handle to that object) at the end of that method call... release it then.
If you declare an object as an instance variable, then by definition you will be done with it when that instance is destroyed... release it in the dealloc method of that class.
Keep in mind that "release" does not equal "destroy." When passing objects around in your application, it may make sense to have more than one handle to that object stored in different places... in that case "release" means "I'm done with this object, but someone else may still be using it." Deallocation only occurs when the number of "handles" (retain count) reaches zero.
Apple has some fantastic documentation on memory management, I would check it out at developer.apple.com.
You essentially have three kinds of objects, each with a different pattern.
Transients Objects
In general, you should autorelease transient objects. These are objects that are allocated locally and do not need to exist beyond the method in which they are called. Or they are passed around from method to method.
Chain of Ownership
When one object exists as an instance field inside another, you should release the "owned" (or "child") object when the "owner" (or "parent") object goes out of existence. This is done in the dealloc method of the parent object:
- (void) dealloc {
[child release]; // child was declared as an instance variable
[super dealloc];
}
Lifetime of the Program
When an object is intended to exist for the lifetime of the program, it usually isn't necessary to call release at all, unless some kind of resource cleanup needs to occur. You can put this in applicationWillTerminate:, which you can look up in Apple's documentation.
(You should probably avoid having such objects, but that is a discussion for another question.)
You have to think in terms of ownership. When you take ownership of an object by calling alloc, new or retain, you're also responsible for releasing it, either by calling autorelease when you return an owned object to the caller, or by calling release.
A general rule is:
Local variable: release it within the same method. When you want to return it to the caller, use autorelease
Class member: release it in the dealloc method
I still have some unclear understand about release and autorelease. What are the difference between both of them? I have this code. For facebook connection. I crash it sometimes when I go to Facebook login, I doubting maybe it is because I don't release the object nicely.? Thanks for any helps
if (_session.isConnected) {
[_session logout];
} else {
FBLoginDialog* dialog = [[[FBLoginDialog alloc] initWithSession:_session] autorelease];
[dialog show];
}
The Memory Management Programming Guide for Cocoa will soon be your best friend. In brief, object instances in Cocoa are memory managed using reference counting (unless, of course you're using garbage collection on OS X). An object indicates that it wants to 'retain' an ownership interest in an other instance--keep it from being deallocated--by sending it a -retain message. An object indicates that it wants to release that interest by sending the other instance a -release message. If the number of objects that have 'retained' and ownership interest in an object drops to 0 (i.e. when the last of the owning instances sends a -release message), the instance with a 0 retain count is deallocated.
It's sometimes convenient to say "I want this instance to be released some time in the future". That's the purpose of -autorelease. Sending an -autorelease message adds the receiver to the current NSAutoreleasePool. When that pool is drained, it sends a -release message to all the instances in the pool. An NSAutoreleasePool is automatically created at the start of each iteration of each thread's run loop and drained at the end of that iteration. Thus, you can do something like this in a method:
- (id)myMethod {
return [[[MyObject alloc] init] autorelease];
}
The caller of this method will get back an instance that they can -retain if they wish to keep it. If they don't retain it, it will stick around at least until the enclosing autorelease pool is drained:
- (void)someOtherMethod {
...
id instance = [obj myMethod];
... // do more with instance, knowing that it won't be dealloc'd until after someOtherMethod returns
}
Releasing means you release that right away.
Autoreleasing means you want the variable to be released on the next autorelease pool.
You use autorelease when you want to keep retaining the variable but don't want to create a memory leak. You use release when you don't need the variable anymore.
Sample:
- (NSNumber *)return5 {
NSNumber * result = [[NSNumber alloc]initWitnInt: 5];
[result autorelease];
return result;
}
Why do we use autorelease there?
If we use [result release] instead, variable result will be destroyed AT that time. Which means that the returned value will be garbage.
If we do not release at all, variable result will be hold FOREVER incurring memory leak.
We can tell every caller to the function to release result but that would be a headache and prone to error.
So we use autorelease. We mark the variable to be released on the next autorelease pool. Basically we mark the variable to be released near the alloc. Hence the mantra alloc is paired with release in the same function holds all the time.
Actually, you'll do fine changing all release into autorelease. Your memory use won't be efficient, however, the effect is minimal. All variables, in all programming language is effectively autoreleased.
Anyway, use ARC.
background discussion:
objective-c is reference counted, so objects are deleted when the reference count reaches 0. release reduces the reference-count immediately, autorelease reduces it when the autorelease-pool is popped
when to use:
use autorelease when allocating the object if
you do not need it after the current function
it will be retiained by some other objet/function and will be released by a later by the retaining code
when the logic of the current function is tricky, so you would have to send release in a dozen different places before doing a return
use "manual" release
to revert a previous retain (in case you are implementing a library)
if you need precise control of freeing objects (e.g. they use lots of memory or the autorelease pool will not be popped for some time)
but really my freand:
read the Memory Management Programming Guide for Cocoa as suggested by Barry and run your code with instruments (zombies and leaks) often to catch any and almost all memory management errors.
Erik
According to the Memory Management Programming Guide for Cocoa:
The autorelease method, defined by
NSObject, marks the receiver for later
release. By autoreleasing an
object—that is, by sending it an
autorelease message—you declare that
you don't want to own the object
beyond the scope in which you sent
autorelease.
Also:
The autorelease method thus allows
every object to use other objects
without worrying about disposing of
them.
After reading the Memory Management Guide I am trying to get my head around what is happening here My understanding "so far" is ...
- (EngineClass *)engine {
return [[engine retain] autorelease];
}
I am returning a pointer to an Engine object.
The retain count of the object is incremented to record we are making a new pointer to the object
Balance the above retain by specifying an autorelease at some future point.
Am I on the right track?
cheers -gary-
I'm not sure I'd say the retain is "to record we are making a new pointer to the object."
The retain-autorelease pair is there to indicate that there's another object interested in the return value, so it needs to stick around at least that long, but the other object doesn't properly own the return value. Without the retain, if the object performing this method is deallocated immediately afterward, the engine might not have any other owners and would also be deallocated immediately. That's not the expected behavior. Doing it this way causes the object's ownership not to go away until the autorelease pool is drained.