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
Related
I just ran into a problem.I use NSMutableArray to keep the Ad ids that need to be loaded. When one id is preloaded, I remove it from the array. Then I find out that, after remove, the unit id became a zombie.
I tried to reproduce this, and I find out that when the Ads id was pulled from array, it is not a zombie.It just become zombie after removed from array. But, there is still a NSString* refer to it, how can this happen? And If it will become zombie at this point, it should become zombie every time. But it only happens occasionally.
-(void)preloadNextRewardVideo
{
if([_allRewardVideoAds count])
{
NSString* adsName = [_allRewardVideoAds objectAtIndex:0]; //the element is not a zombie here
GADRewardBasedVideoAd* ads = [self ensureRewardVideo:adsName];
if(![ads isReady])
{
_currentRewardVideoName = adsName;
[_allRewardVideoAds removeObjectAtIndex:0];
GADRequest *request = [GADRequest request];
[ads loadRequest:request withAdUnitID:adsName]; //here, adsName is a zombie
_isRewarLoading = YES;
}
}
}
It's worth taking a close look at cocoa's memory management policies. The thing here (it seems to me) is that when your code assigns the string adsName, the object the preloadNextRewardVideo method is part of doesn't take ownership of the string-object that adsName is pointing at ('ownership' in this context means either allocating and initializing space for it through alloc/init, new, copy, etc, or sending it an explicit retain message). All you have is a local variable that points at a string-object owned by the _allRewardVideoAds array. Yes, making the assignment increases the retain count, but that retain is autoreleased, and limited to the scope of this method. As soon as this method ends, nothing is going to own that string-object, and it will deallocate.
This would not be an issue (and would not create the NSZombie flag) except that you just sent adsName to a different object (GADRewardBasedVideoAd* ads) that I'm guessing does not retain it either. Of course, ads is also autoreleased (nothing owns it outside of this method), but what is that, a race-condition over whether ads or adsName is deallocated first? I suspect you do have a race-condition because NSZombie only shows up sometimes, but I don't know enough about the internal mechanisms of autorelease to know how that might work.
I think NSZombie is just telling you that you have an object that is:
in use by an external object, and
due to be destroyed shortly though autorelease.
ARC is anticipating a problem, and using NSZombie to let you know.
You could fix this either by using the property setter (e.g. use self.currentRewardVideoName = adsName) which retains the string-object globally for this object, or by locally copying it (NSString* adsName = [[_allRewardVideoAds objectAtIndex:0] copy]) which makes sure that your object owns the string to the end of the method.
Since you don't enable ARC that means you need to manually manage the memory by yourself. Since you don't enable ARC that means you need to manually manage the memory by yourself. Even though most of APIs will return an auto released object from a method but that's not always be the case.
For this case, NSArray retains the objects contained in itself so it may not need to return an auto released object from objectAtIndex: method since it should be retained by itself as an optimization. In this case I suggest you to call retain the object when you get it from the array and release it before the end of this method. That would help for this case.
I am not clear about how to use autorelease;
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
RetainTracker* tracker = [RetainTracker new];
[tracker retain];
[tracker retain];
[tracker autorelease];
[pool release];
Is there any memory leak in the above code?
I know the autorelease just puts tracker into NSAutoreleasePool, without modifying the reference count for tracker. When i call [pool release], the object receives one message release, then the reference count of tracker is 2. So the compiler can't call the dealloc function of object tracker, so there is a memory leak.
So i get this: we shoul call retain and release same times, is it right?
If you're new to Objective-c, you should be using Automatic Reference Counting. Almost everyone should. But for the sake of understanding:
An object has a reference count of how many objects have a reference to it. When it drops to zero, the object is not referenced by anything and is deallocated. Every method in Objective-C is responsible for releasing any object it retains. The problem is, if a factory method's job is to create an object, it's breaking the rules by not releasing an object it retained (in this example it was retained because it was created). If the method called release on the object right before returning it, it would be returning the address to an object that is already gone. So, there is autorelease, which temporarily delays the release until the calling method can retain the object the called method created.
In your example above, if you got rid of the 2 retains, and only called autorelease, then the object would get released and deallocated when the autorelease pool is released and (right before deallocation) is drained, meaning it calls release on all objects in its pool, tracker being one of them because calling autorelease on tracker added it to the pool.
new is equivalent to doing an "alloc" & "init", so retain count on tracker on that line is 1.
Then you increment the retain count 2 more times to give a total retain count of 3.
Autorelease sets the tracker to be released when the pool is released (and the retain count is decremented as well). But it's already retained 3 times, so it doesn't really get released.
And yeah, there is a memory leak with the retain count being greater than 0 and no reference to "tracker" outside of that method (that is, unless you're using "tracker" in an instance variable).
It's very good to know the basics of memory management; but if you want to save yourself a ton of headache, just do what everyone else here seems to be saying and simply enable ARC.
EDIT: And to finish your question, you should make sure every call to retain is balanced with a release. You also do a "new", which also increments the retain count so you need to "release" because of that as well.
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 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]
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.