In my app I have a NSError that I declare locally:
NSError *error;
Do I release it in dealloc method or do I need to release it in the method I declare it?
Please read the Cocoa Memory Management Guide, memory management is something you should understand perfectly. (And it’s not hard.) If you declare a variable in a method, you don’t have a pointer to it in dealloc, therefore you can’t release it there – you can only release it before it goes out of scope. Another question is if you should release it at all. That depends on whether it is a stack-based, autoreleased or retained variable:
float foo[] = {1, 2, 3}; // stack-based, no releasing necessary
NSString *foo = [NSString stringWithFormat:…]; // autoreleased, you must not release it
NSString *foo = [[NSString alloc] initWith…]; // retained, you must release it
You need to release it locally -- assuming you create it by alloc/new/copy or else retain it. (If you just get it from somewhere else without allocating or retaining, then it doesn't belong to you and you shouldn't release at all.)
Otherwise, once it goes out of local scope you have no access to the pointer and the object will leak.
You need to release it locally. Because in dealloc method we release class variables or class data members and those variables that are used through out the implementation file (like extern variables).
Related
I have a question. In my .h:
NSString *string;
#property(nonatomic, retain)NSString *string;
In my .m:
string=[NSString stringWithFormat:#"%#", otherStringWithValue];
Ok, "stringWithFormat" is an autorelease method. Need I release "string" in dealloc??
only self.string = .... will retain your stringWithFormat.
so you dont need to release it. but beware that you string will be released and your app get crashed when your try later to access it. if you want to keep your string so make
self.string = .....
and release it on dealloc
If the string that you are declaring is a part of the property in the above code then yes, even though you have to initialize it. The ownership is still yours to take care off.
The attributes are applied to property only.
Properties can not be accessed directly. It can be accessed via "." only.
So, when you write,
string=[NSString stringWithFormat:#"%#", otherStringWithValue];
you are accessing variable. So, no retain will be called on it. Also, stringWithFormat will return autoreleased object. So, no need to release it in dealloc. However, you can not access this variable beyond the scope because you do not know, when will it get released.
If you write,
self.string=[NSString stringWithFormat:#"%#", otherStringWithValue];
you are accessing property and its value will be retained. So, you will have to release it in the dealloc method.
Just Use ARC.
Seriously. It means you no longer need to worry about retain/release (though you do have to worry about reference cycles, which you would have had to worry about anyway).
If you are not using ARC, then the code above crashes becaus you are not taking "ownership" of the string (by retaining it). Either retain it correctly:
[string release];
string=[[NSString stringWithFormat:#"%#", otherStringWithValue] retain];
Or use the setter, which (if it is automatically generated) will retain it correctly:
self.string=[NSString stringWithFormat:#"%#", otherStringWithValue];
In -dealloc, you then have to release the ivar, or you can just use the setter (which will release it automatically for you):
self.string = nil;
Before ARC, my rule of thumb was to almost always use the property syntax, since it just does the right thing.
instead of this:
string=[NSString stringWithFormat:#"%#", otherStringWithValue];
do this:
self.string=[NSString stringWithFormat:#"%#", otherStringWithValue];
Now, you need to release the string in your dealloc. Though, the +stringWithFormat returns autorelased object but you've declared a retained property so, you're responsible for releasing it.
This code will introduce memory leak because stringWithFormat returns autorelease object and you have retain string, so when you assign string the value of stringWithFormat it will provide new autorelease object.But whatever memory you have retained for string is still there because its retain count is still 1, so it will not get released.but if you tried to release string it will crash because after assignment it will contain autorelease object.
This is my sample code....i am creating the class object as NSDictionary.Here it shows the leak,Where i release that object it's not right place to release this object?
How can i release this object.
TanX in advance.
NSDictionary *locationDictionary = [[CJSONDeserializer alloc]deserializeAsDictionary:webresponse error:nil];
NSArray *placemarkArray = [locationDictionary valueForKey:#"Placemark"];
NSDictionary *tempDictionary = [placemarkArray objectAtIndex:0];
NSDictionary *pointDictionary = [tempDictionary valueForKey:#"Point"];
NSArray *coordinateArray = [pointDictionary valueForKey:#"coordinates"];
NSNumber *numberLongitude = [coordinateArray objectAtIndex:0];
NSNumber *numberLatitude = [coordinateArray objectAtIndex:1];
The CJSONDeserializer class has convenient constructor. So use that.
CJSONDeserializer *jsonDeserializer = [CJSONDeserializer deserializer];
The deserialize with that object.
NSDictionary *locationDictionary = [jsonDeserializer deserializeAsDictionary:webresponse error:nil];
So you need not to release that.
You are calling alloc on the CJSONDeserializer so you own it. When you are done with it, you need to release it. I don't see you calling release on it.
The rest of the variable are obtained by not calling alloc, copy, new or mutableCopy so you don't own them. They have been auto released. That's the convention.
This is a must read:
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html
Specifically, the rules:
You own any object you create
You create an object using a method whose name begins with “alloc”, “new”, “copy”, or “mutableCopy” (for example, alloc, newObject, or mutableCopy).
You can take ownership of an object using retain
A received object is normally guaranteed to remain valid within the method it was received in, and that method may also safely return the object to its invoker. You use retain in two situations: (1) In the implementation of an accessor method or an init method, to take ownership of an object you want to store as a property value; and (2) To prevent an object from being invalidated as a side-effect of some other operation (as explained in “Avoid Causing Deallocation of Objects You’re Using”).
When you no longer need it, you must relinquish ownership of an object you own
You relinquish ownership of an object by sending it a release message or an autorelease message. In Cocoa terminology, relinquishing ownership of an object is therefore typically referred to as “releasing” an object.
You must not relinquish ownership of an object you do not own
This is just corollary of the previous policy rules, stated explicitly.
If you are just after numberLong. and numberLat. retain just them until your done with them.
And if you no longer need the locationDictionary as a whole you can now [locationDitionary release], but only after retaining or finishing with what you need from it.
I have a beginner's question about releasing variables and not wasting memory...
I don't quite understand when to release variables. I understand that I should always do this if I have assigned them in my header file (in my #interface section and my #property commands). I release them in my -(void)dealloc function.
However, what am I supposed to do with variables that I happen to use in some of my methods, e.g.:
for (int temp = 0; temp < 3; temp++) {
// do something...
}
[temp release];
This is obviously wrong (at least xCode tells me so), as 'temp' is undeclared. But why? I've declared it as an int and temp thus takes up space in my memory, I'm sure. How do I tell the program to free up the space temp has taken after I don't need it anymore? I'm sure this is obvious, but I simply don't get it.
I'd be very happy for any suggestions for a beginner of how not to be a memory pig and to have 'memory leaking' everywhere in my apps...
You declared it as an int in the scope of the loop. Once the loop is done, it goes out of scope.
Also, you can not release an int, which is a primitive type. You can only release a subclass of NSObject. A good rule of thumb is that you eventually have to release anything that you called alloc or retain on.
Edit: For your edification, memory management only applies to objects allocated from the heap. That would be NSObjects obtained via "alloc" or must C-level memory allocated with something like "malloc()". Declaring a variable like "int x" is called an "auto" variable in that is is created on the stack and will AUTOmatically disappear then that block ends (the end of a "block" being the end of the function or perhaps the end of a {} pair or even the end of a for/if/while block.
Since Objective-C is basically just a special version of C (with messages), it does not create permanent objects unless you explicitly tell it to. This is different form languages like Python or Javascript.
You only need to release objects, and temp is an int, not an object.
As far as when to release objects, Apple's docs explain that better than I can: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html
You do only release objects, and not primitive types. For example you create an array with
NSArray *myArray = [[NSArray alloc] init];
This initialization allocated memory which you have to free after your done using your array, it's your responsibility, else there will be memory leaks. You can do that in the dealloc section of a controller, or at the end of a method, or even after you've enumerated through the array and no longer need it.
If you create instances of objects with other methods than alloc, copy or new(rarely used) you have to release them. If you call retain yourself on an object you have to release it as well.
Please refer to apples memory management rules, which have been posted earlier.
There are two ways to store information in RAM in C and c like things, primitives which are allocated automatically by the compiler, and memory chunks allocated by you in your program.
Variables allocated for you by the compiler are called "automatics" and can be marked by the essentially unused (because it is the default) "auto" keyword. Automatics are bound to the scope in which they are declared and go away when it ends. Regular variables, like "int x" are automatic.
Notably, pointers are typically automatic. However, the things they point to are not. Those would be the thing you asked to be allocated.
In objective-c, things are allocated with the alloc message. However, sometimes a class will call this for you, so you might not see it. To help make it clear what you should do, there is a tradition: If you get an object where you alloc'ed it, got it from a class method with the word "copy" in the method name, or sent it a "retain" message, then you own a share of it, and it won't go away until you send it a release message.
If you didn't get the object through one of those means, you must not release it, because you don't have a share in it.
So, in summary: regular variables (int, short, char, double, float, long) are automatic, no need to allocate it. Pointers are also automatic, however, the things they are pointing to are not. In obj-c, you own a share if you alloc'ed it, copy'ed it, or sent it a retain message.
You can't release an integer...
Release works only with instance of Objective-C classes.
Variables such as integers are placed on the stack, and they does not persist after a function/method call, unless allocated explicitely.
You only release objects. If you use the alloc, init procedure to create an object you must release it. If you retain an object you must release it. If you use a method that has the word "create" in it, you must release it. Anything else, the system will handle for you.
Primitives do not need to be released, only objects.
Biggest thing to keep in mind is that whenever you "alloc" or "retain" an object, put a corresponding "release" or "autorelease".
you see an error on the line [temp release]; because temp is not in scope. temp will not be seen outside of the for loop you created.
you do not need to clean up the memory of temp, since you have not claimed ownership of it(see Memory Management Rules): http://developer.apple.com/library/ios/#documentation/general/conceptual/DevPedia-CocoaCore/MemoryManagement.html
examples of objects where you do not need to release/manage memory:
NSArray *myArray = [NSArray array];
NSNumber *myNumber = [NSNumber numberWithInt:5];
NSString *myString = #"Hello World";
NSInteger i = 5;
int x = 2;
examples of objects where you do need to release/manage memory:
NSArray *myArray = [[NSArray alloc] initWithObjects:#"Hello", #"World", nil];
NSNumber *myNumber = [[NSNumber alloc] initWithInt:5];
NSString *myString = [[NSString alloc] initWithString:#"Hello World"];
-
typically, when your completely done using an object you own, you clean up its memory
see apple's docs for explanations on properties: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html#//apple_ref/doc/uid/TP30001163-CH17-SW1
setting a property with assign or readonly: you should not worry about releasing its memory, as you don't own it
property with retain or copy: you claim ownership of the object and need to release it at some point
this answer won't answer/solve all memory management questions/concerns, but it may shove you in the right direction
I have a question about a retain and a NSString, if I have a method who a return a NSString, and I put the return NSString in a nsstring variable, I must do a retain or not?
NSString *myString = #"";
myString = [self methodWhoReturnString]; // I must do this?
myString = [[self methodWhoReturnString]retain]; // Or I must do this?
The Apple Developer Documentation on Memory Management explains the scenarios where you retain/release objects.
Simply put, if you want the string to stick around, you need to retain it until you're finished with it. If that is just the scope of the current function, you can get away without retaining it as if the string is already autorelease'd (likely) it won't get released until your function finishes and the current AutoReleasePool is purged.
Bear in mind that an NSString * could actually be pointing to an NSMutableString *. If it matters to you if the string is changed by some other function without you realizing, be sure to copy it: NSString * myCopyOfString = [mystring copy];
If the string is set to autorelease, which it most likely is, then yes you will need to retain it somehow. I would suggest doing this though:
myString = [[self methodWhoReturnString] copy];
this ensures you have retained the data in the string not just a reference to a string that might still be controlled elsewhere. Be sure you release your copy later!
Usually, methodWhoReturnString would return an autoreleased string, which means you should retain it if you want to keep it around.
So, if methodWhoReturnString is your method, I believe that to keep with convention you should return [stringToReturn autorelease]; from that method, and then retain it if you want to keep it.
You use retain if you're going to be using myString at a later point in time (i.e. after the current method has returned) to prevent it being autoreleased.
You don't need to use retain if it's just a temporary variable used within the current method, since in that case you do want it to be autoreleased.
One special case is properties. If you call self.blah = foo, you don't need to retain foo, since the setBlah: method should do it for you.
(there's a whole load of other complexities and edge cases, but this is a good rule of thumb to get you started on understanding what to do)
Given the code you provided, you shouldn't call -retain. In your example, the return value of a method that returns an instance of NSString is assigned to myString, an automatic local variable. If the assignment had been made to an instance variable or a static variable, you would want to call either retain or copy to guarantee that the reference remains valid beyond the end of the local scope.
In this case though, the reference to the NSString instance is stored in a variable that will be destroyed automatically at the end of the local scope, so your code needn't concern itself with the object's lifetime.
Any method that has alloc, new or copy in it automatically retains and infers that you have ownership of the object. All others shouldn't. It would be helpful if you had more context though. If we are in a contained method where this string is used briefly, then you probably don't need to retain. If it is going to be used for a while, you might want to use the #synthesize syntax to make it a property of the class you are in. When you use #property and #synthesize and call something like self.myProperty = something it will automatically retain.
In my own iPhone Application I have used a number of nsstring variables to store values. But sometimes its value becomes Invalid! Does anybody know what may be the reason? Or tell me about the situation when a nsstring variable becomes Invalid?
NSStrings are also objects. They go by the same memory management rules. If you sin against those rules you will get a pointer to invalid memory and it will look like "invalid" data.
For example:
myString = [NSString stringWithString:#"foo"];
This will create an NSString* that's got autorelease on. When you're assigning it to an ivar that autorelease pool will soon pop putting the retain count back to 0 and dealloc'ing it while you still have a reference to it!
Naughty.
Instead, either retain it or use:
myString = [[NSString alloc] initWithString:#""];
This returns an owning reference. Remember to [myString release]; in dealloc.
This is just one example/case of bad memory management. Read the docs on how to properly manage your object lifecycle. Really.
They are being autoreleased. If you create a string using a convenience method (stringWithString, stringWithFormat) it will be added to the autorelease pool.
To stop it being released automatically, sent it a retain message and a release message when you have finished using it so that the memory is released. You can also set up properties to do this semi automatically when you assign the string to a member variable
There are a lot of articles on iPhone (and Mac) memory management here on SO and on the interwebs. Google for autorelease.
If this is for a device with fairly limited resources such as the iPhone, you should use [[NSString alloc] init*] over the static convenience methods, as you will put less pressure on the autorelease pool and lower your memory usage. The pool is drained every message loop, so the less objects to enumerate the better.
You should also be aware that autorelease objects in a loop will generate a lot of garbage unless you manage a local autorelease pool.
did you copy or retain the NSString ?
I asked the same question. And the following answer was the best of convenience. Just use:
[myString retain];
And then in dealloc method (e.g. viewDidUnload):
[myString release];