I have a NSMutableArray instance called entries and I would like to send one of its value (which is a NSDictionary) to a method, but I'm thinking of how to avoid it to leak or properly release it. Here's what I'm doing right now:
NSDictionary *pdata = [self.entries objectAtIndex:indexPath.row];
[self start_download:pdata];
[pdata release]; // <--> Is it ok to do this ?
Thx for helping,
Stephane
you did not alloc, copy or retain pdata so you don't release it
You should absolutely not release pdata, since you never retained it. -objectAtIndex: returns a non-owned object. If -start_download: needs to refer to pdata after it returns (e.g. if it holds onto it for some asynchronous process) then it should retain pdata itself, and subsequently it should release pdata when it's done, but that's orthogonal to the bit of code you pasted.
If you haven't already done so, you should read the Cocoa Memory Management Rules.
Do you have a delegate method for start_download to handle with the download finished? You should release it then.
I would have start_download do a retain on pdata and then release it when it's done. It's always a good idea to have routines that need to hang on to data to a retain and release themselves, that way you don't care how the object got to you and what's going to happen to it after.
Related
This maybe too basic but I couldn't find an exact answer. I'll be happy to delete/close this post if anyone point me to similar posts.
I want to call method "getString" to return a formatted string and set to my label like this:
-(NSString*) getString {
NSString *result = [NSString stringWithFormat:#"blah blah %#", someOtherString];
return result;
}
-(void) viewDidLoad {
someLabel.text = [self getString];
}
This code worked for me, but I am concerned that result is allocated by a convenient method thus may be auto-released before it got retained by the label. Is it true? If so, when exactly would an object from convenient method get released?
Second question, if in case I have to use [NSString alloc] to create my own string object. Where and how should I release it?
Thanks in advance
Leo
It isn't true that the object will be autoreleased before you retain it. The details of when the pool gets drained are unimportant to answer this question, except that it can't happen during your code unless you call drain or release on the pool. If your function calls another function, except in some specific edge cases both the function you call and the function you called from need to exit before that thread can do anything else. The autorelease pool is thread-specific.
To answer your second question, if you alloc an object you should release it when you've finished using it. Simple as that. That includes when you pass it to other code that needs it, because it should be up to that other code to claim ownership if it needs to.
This code worked for me, but I am concerned that result is allocated by a convenient method thus may be auto-released before it got retained by the label.
Yes, it will be autoreleased because it is returned by a method whose name does not contain new, alloc or copy. No, this won't happen before the calling method viewDidLoad returns.
In fact, the autorelease-pool, to which it's added will probably be the one set-up and teared-down by the runloop, so nothing is going to happen to it until the end of the current iteration through the runloop.
I want to check if an object has some count or not Here is my testing code
NSMutableArray *array=[[NSMutableArray alloc]init];
if(array)
{
NSLog(#"hiiiiiii");
}
CASE-2
NSMutableArray *array=[[NSMutableArray alloc]init];
[array release];
if(array)
{
NSLog(#"hiiiiiii");
}
Here in both cases i got same output as printed "hiiiiiii".
Can anyone tell me how will i check if my object need to release or already released.
I know that i should have track of my object's counters but i am at a stage where my code is too much complexed and i need help..
Please help..
ALso tell that how much memory leak is allowed by apple?
There is no way to check if you "should" release an object. Doing something like "if(object)" only checks the pointer to the object. It will return true even if the object it was pointing to was destroyed a long time ago. This is what happens in your second case. The object is destroyed when you call release, but the pointer is still pointing at something, so it returns true. It will only return false if the pointer is set to nil.
However, there is a simple set of rules for calling release. If you ever call "alloc", "new", "copy", "mutableCopy" or "retain" on object, you must always call "release" or "autorelease" on it. That will prevent any memory leaks.
Apple does not have a publicized amount of memory leaks allowed. It is always safest to eliminate any known memory leaks; plus, it will mean better performance for your customers.
In your second case you are releasing the NSMutableArray but still it store a non zero value although it's no longer for use (To call function OR fetch value).That the reason your if condition got true.
Just remember whenever you call release on any object, Do'nt forget to assign nil to that, So your second code should look like below.
CASE-2
NSMutableArray *array=[[NSMutableArray alloc]init];
[array release];
array = nil;
if(array)
{
NSLog(#"hiiiiiii");
}
There is a simple rule of memory management in Object-C if your alloced or retain any object you must call release on that,
Read memory management Guide from Apple.
I have Object:
MyClass *obj= [[MyClass alloc] init];
What's the difference between:
[obj release]; // Only obj own this object.
and:
obj = nil;
Does iOS deallocs obj when i set obj = nil?
I have a pointer, sometime i set it point to an object, sometime do not. So, when i want release a pointer i must check is it nil?
This answer from the previous decade,
is now only of historic interest.
Today, you must use ARC.
Cheers
The very short answer is DO NOT just set it to nil. You must release it. Setting it to nil has no connection to releasing it. You must release it.
However it's worth remembering that if it is a property, then
self.obj = nil;
will in a fact release it for you. Of course, you must not forget the "self." part !!!!
Indeed,
self.obj = anyNewValue;
will indeed release the old memory for you, clean everything up magically and set it up with the new value. So, self.obj = nil is just a special case of that, it releases and cleanses everything and then just leaves it at nil.
So if anyone reading this is new and completely confused by memory,
You must release it, [x release] before setting it to nil x=nil
IF you are using a property, "don't forget the self. thingy"
IF you are using a property, you can just say self.x=nil or indeed self.x=somethingNew and it will take care of releasing and all that other complicated annoying stuff.
Eventually you will have to learn all the complicated stuff about release, autorelease, blah blah blah. But life is short, forget about it for now :-/
Hope it helps someone.
Again note, this post is now totally wrong. Use ARC.
Historic interest only.
Is It Necessary to Set Pointers to nil in Objective-C After release?
Release, Dealloc, and the Self reference
Setting an object nil versus release+realloc
Read the above. They answer your Q comprehensively
iOS does not support garbage collection, which means that doing obj = nil would result in a memory leak.
If you want automatic control over deallocation, you should do something like: obj = [[[NSObject alloc] init] autorelease] (you must NOT release it if you do that).
Autorelease would cause the object to be automatically released when the current NSRunloop event ends.
The NSRunloop automatically drains it's NSAutoReleasePool for each event iteration, which is usually very helpful.
Setting an object nil will create a memory leak(if you are taking ownership by alloc,retain or copy) because we are not having a pointer to that particular memory location.
so if you want to dealloc an object you have to take out all ownership of an object before making it nil by calling release method.
[obj release];
obj=nil;
Should I release strPhone? What about the coreFoundation object being cast to an NSString? What happens to it?
strPhone = [[NSString alloc] initWithUTF8String: [[(NSArray *)ABMultiValueCopyArrayOfAllValues(theProperty) objectAtIndex:identifier] UTF8String]];
Thanks for helping me understand.
You should release or autorelease both. For the NSString, any time you use alloc + init to create an object you are settings its reference count to 1. You are responsible for releasing it when done or autoreleasing it now to allow it to be released at the end of the run loop.
For the CFObject, ABMultiValueCopyArrayOfAllValues returns a CFArray which is “toll-free bridged” to NSArray (meaning it can be used interchangeably with NSArray). Anytime a copy is done - as is implied by the method's name, you are responsible for releasing the returned object. Again, you can release it immediately after you are done with it or autorelease it now to have it be released when the run loop completes.
Yes, both. See Apple's memory management guide for a complete but still pretty brief rundown of memory management in Cocoa.
Remember to NARC on your memory management.
New, Allocate, Retain, Copy. Those are the methods that create objects that YOU'RE responsible for releasing. Aside from those four methods, any new object you get is autoreleased and you don't have to explicitly handle its deallocation.
I have some code which I think has extra release statements.
Is the code incorrect?
What is the end result?
I don't understand memory management well yet - even after reading lots of articles and stackoverflow answers. Thanks for straightening me out.
Update: The attached snippet works fine, but other code has the over-release problem
NSMutableArray *points = [NSMutableArray new];
for (Segment *s in currentWorkout.segments) {
[points addObjectsFromArray:[s.track locationPoints]];
}
[routeMap update:points];
[points release];
Your code is correct, but inadvisable. new acts as an implied alloc, which creates the object with a retain count of 1.
I think the last time I used new was in 1992; it's not wrong, but alloc/init is considered better practice, because it is clearer what you are doing. Please read Apple's guide to memory management, it is a comprehensive summary of the situation.
No messages can safely be sent to a deallocated object. Once an object has been released a sufficient number of times, it's deallocated. Any further messages sent to that object are going to an object that isn't there anymore. The precise result isn't completely predictable, but it usually ends in a crash. If you're less lucky, it could end in much stranger ways — for example, you could theoretically wind up with an Object A getting dealloced early and Object B allocated in the same memory location, then Object B receiving messages meant for Object A that Object B does understand but isn't supposed to receive at that time.
Basically, follow the rules. Think of it in terms of ownership. If you've claimed ownership, you need to release that ownership. If you don't own the object, you must not release it.
Take a look at this article online: http://weblog.bignerdranch.com/?p=2 .
It seems to imply that calls to release without a corresponding preior call to retain will result in a BAD_ACCESS error.
A short answer is, if you increasing the retain count of an object and you no longer are using it you should release it, otherwise you shouldnt...
So when ever you do a [objectName alloc] you are increasing the count by 1, when you use such methods as [NSString stringWithString:] these methods return an autoreleased object so you dont need to release it...if you instead did something like [[NSString stringWithString:]retain] then you are increasing the strings retain count and you should release it after you are done using it.
Im not too sure if new increases the reference count (i suspect that it would), you can always check your retain count by doing [object retainCount]... though note that even if the retain count is greater than 0, it does not mean you need to release the object, because some other class might have a reference to the object and therefore has its retain count increased by one and its the responsibility of the other class holding the reference to release it.
Hope this helps
you should use:
NSMutableArray *points = [[NSMutableArray alloc] init];
[...]
[routeMap update:points]; //if routemap stores the points, it will need it's own release retain
[points release]; //if there is a retain in the method above, reference will not be cleared
if unsure, use the build->analyze command, it will search your code for leaked references
you can get the official memory management guide from https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html