Copying NSDate objects and releasing - objective-c

if I do this:
NSDate *dateStart;
[dateStart alloc];
// Initialise with a date somewhere here..
..
// Modify the start date.
dateStart = [chosenDate copy];
Should I be doing a [dateStart release] before assigning the dateStart pointer?
I'm from a C/C++ background and I don't understand the whole ObjectiveC/iOS garbage collection behaviour (if indeed there is any). My C background is telling me I should be freeing the initial NSDate object that dateStart is pointing to. Would that be correct?

Yes since you allocated it before you should release it before this line
//Release it before reassign
[dateStart release];
dateStart = [chosenDate copy];
Also notice that its preferred that you do the allocation and initialization on the same line, dont break them to multiple lines
So this
NSDate *dateStart;
[dateStart alloc];
Would change to
NSDate *dateStart = [[dateStart alloc] init....];

Related

potential leak value stored never read in NSMutableArray

NOTE: i want to alloc my NSMutableArray and then assign data in it.
i got leak in below code
NSMutableArray *responseArr=[[NSMutableArray alloc]init];
responseArr =[response valueForKey:#"result"];
Also in here value stored never read
NSString *name=_txt_name.text;
if ([name length]==0) {
name=#"";
}
Also leak in below
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd/MM/yyyy HH:mm:ss"];
//below here i get leak
NSDate *dateStart = [[NSDate alloc] init];
dateStart = [dateFormatter dateFromString:startDate];
EDIT :
I have disable ARC using -fno-objc-arc in reachability Class even i get below leaks
This line
NSMutableArray *responseArr=[[NSMutableArray alloc]init];
Allocates a new NSMutableArray and assigns a reference to it to responseArr
This line
responseArr = [response valueForKey:#"result"];
Takes a value from a dictionary (that presumably is a reference to an NSMutableArray) and assigns that to responseArr. At this point there are no more references to the original NSMutableArray that you allocated, so it will be deallocated.
You can just say:
NSMutableArray *responseArr = (NSMutableArray *)response[#"result"];
Similarly with your date code, you could just say:
NSDate *dateStart = [dateFormatter dateFromString:startDate];
There is no need to assign an initial value, only to throw it away.
None of the code you have shown will cause leaks, assuming you are using ARC.
If you aren't using ARC, then start using ARC!
A. First snippet
Using MRC (MRR) you have to balance allocations with +alloc your own:
NSMutableArray *responseArr = [[NSMutableArray alloc]init];
responseArr = [response valueForKey:#"result"];
In the first line you allocate an instance of NSArray. You have to (auto-)release it later, otherwise it is a memory leak. I think you misunderstood that you create a new instance of NSArray using -valueForKey and assign the value of this new reference to responseArr. (Therefore you do not need a mutable array.) After that you created two objects having only one reference to the new one, you can never release the old one.
Do something like this:
NSArray *responseArr = [[NSArray alloc]init];
NSArray *resultArr =[response valueForKey:#"result"];
[responseArr release];
You do not have to do that with the object referred by resultArr, because it isn't created with +alloc-init. Here you get an introduction to ownership.
B. Third snippet
It is the same with the last example:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
You +alloc-init that instance object, but there is no release in your code. Therefore it cannot be released anymore, when the reference dateFormatter loses its extent (lifetime), i. e. returning from the method.
Add this code at the end of the method:
[dateFormatter release];
C. Second snippet
The second example has a different problem: You assign a value to the var name without using the variable in the code below. So assigning the value is meaningless.

alloc + init memory usage mechanism

I am just curious to know when an object has made by alloc, and a piece of memory allocated to it, why init don't use that piece of memory and changes the address of object?
NSDate *t = nil;
NSLog(#"t = %p",t); // t = 0x0
t = [NSDate alloc];
NSLog(#"t = %p",t); // t = 0x100107af0
t = [t init];
NSLog(#"t = %p",t); // t = 0x1001035a0
Two-step initialization allows us to do these kinds of things (namely, substituting an instance of a class for another depending on the initializer called). Class clusters all over Foundation and UIKit take advantage of this to return instances optimized for a particular use-case. For example, UIColor itself is just an interface for its subclasses that implement color caching (all the named initializers like +blackColor), the RGB color space (+colorWithRed:green:blue:alpha), the black and white color space (+colorWithWhite:alpha:), CIColor compatibility, etc. And so NSDate is too. When you call -init, Apple has means and motive to return a different object that implements the same interface as NSDate as an optimization because you honestly shouldn't care what you get as long as it doesn't launch the missiles when you try to message it properly.
As of the latest iOS SDK, calling [NSDate alloc] always returns the same memory location. You can verify this behavior with the following code:
NSDate *date1, *date2;
date1 = [NSDate alloc];
NSLog(#"date1: %p", date1);
date1 = [date1 init];
NSLog(#"date1: %p", date1);
date2 = [NSDate alloc];
NSLog(#"date2: %p", date2);
date2 = [date2 init];
NSLog(#"date2: %p", date2);
I suspect that it has to do with the fact that NSDate is a class cluster.
If the private subclasses of a class cluster have different storage requirements, it's impossible to know inside of alloc how much memory to allocate. One approach to solving this problem, and it appears this is the approach that Apple is using with NSDate, is to let the init and factory methods handle all the memory allocation, since those methods know what private subclass is actually going to be used.
At that point, all alloc is doing for you is allowing the user to preserve the [[NSDate alloc] init] pattern that's used for object creation everywhere in Objective-C. Since the memory location returned by alloc is always discarded, alloc may as well just return a fixed memory location, which is what it appears to be doing.

Memory leaking from object that I do not alloc

I have the following function, which results in *timeString leaking memory. I am fairly new to Objective-C (and memory management), but I read that you only need to release objects that you alloc in the first place. Because I alloc *formatter, and then set that to *timeString, does this mean that I now have to release *timeString too?
Here's the code:
-(NSString *)getDate{
NSLog(#"getDate");
NSDateFormatter *formatter;
NSString *timeString;
formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"yyyy-MM-dd"];
timeString = [formatter stringFromDate:[NSDate date]];
[formatter release];
return timeString;
}
EDIT: Here is where the getDate function is called:
-(NSString *)getFileName{
//nameofXMLFile = page_##
NSString *nameOfFile = [NSString stringWithString:pageTitle];
//nameOfXMLFile = page_##.DataCheckSheet.xml
nameOfFile = [nameOfFile stringByAppendingString: #".DataCheckSheet.xml"];
NSString *dateString = [self getDate];
dateString = [dateString stringByAppendingString: #"_"];
NSLog(#"datestring: %#", dateString);
dateString = [dateString stringByAppendingString:nameOfFile];
NSLog(#"datestring with append: %#", dateString);
//nameOfXMLFile = yyyy-MM-dd_page_##.DataCheckSheet.xml
nameOfFile = dateString;
return nameOfFile;
}
As you already correctly stated, all objects, that aren't explicitly alloced, are per definition 'autoreleased', which means they will be destroyed, once they leave the scope of the function that defined them.
To keep an object valid longer than that, for example, by keeping it around as a class object, you would call 'retain' on it.
This 'retain' needs to 'released', just like an 'alloced' object.
By passing the reference to the object in question as return value, the scope of the object gets expanded to the function, which called the function in the first place...which means, the object would be destroyed at the end of the calling function, unless it is retained by then.
nameOfFile is still that very object in question, since you copied the address of dateString to that variable, effectively erasing that string from existence (it will thereby get autoreleased).
Try to avoid such assignments, unless you have a reason for them, to avoid confusion.
In short: If you have a chain of function calls and returns, make sure, that there isn't a 'retain' somewhere along the line, which doesn't get released appropriately, and you'll be fine.
Your best bet to understand leaks is to use Instruments and its "Leaks" template.
The "leak" instrument will show you what objects are leaked and you will be able to jump right away to the ObjectAlloc instrument to see retain/releases calls to the leaked object. You should then be able to find where missing release(s) are.
As is, your code looks OK wrt memory management. However most of the strings created here are autoreleased, which means they will be effectively released when the outter autorelease pool will be drained. Until the pool is drained, your object might appear to leak.
In typical applications, the main thread has an autorelease pool automatically installed by NSApplication/UIApplication, yet the pool is drained only when the application receives events (see this question)
In a usual detached thread (using NSThread or pthread), you have to install your own pool(s) (and drain them regularly).
GCD dispatch queues install their own autorelease pool and drain them from time to time.

Why do I need to retain the result of NSDateFormatter dateFromString:

I have an NSDate* that I'm storing as a property with the retain keyword:
#property (nonatomic, retain) NSDate* startTime;
I use it as follows:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"h:mm a"];
startTime = (NSDate*)[[NSUserDefaults] standardUserDefaults] objectForKey:#"StartTimeKey"];
if (startTime == nil)
startTime = [[dateFormatter dateFromString:#"8:00 am"] retain];
Why do I need to retain the result of the dateFromString: message, but I don't need to retain the result of objectForKey: ?
I just upgraded to XCode 4.2 and I'm now using the LLVM GCC 4.2 compiler. Before the upgrade, the code worked fine without the retain. Now it crashes (later in the code when I access the startDate property) without the retain message.
The problem is that you wrote this:
startTime = blah blah blah;
You're setting the instance variable startTime directly. If you do this instead:
self.startTime = blah blah blah;
then the compiler will turn it into this:
[self setStartTime:blah blah blah];
and the automatically-generated setter method will do the retain for you.
If you do this:
#synthesize startTime = _startTime;
then the instance variable will be named _startTime, making it easier to remember to use the property instead of assigning to the instance variable directly.
The answer is in the Memory Management Programming Guide on page 11.
You own an object you create (that is you do not need to retain it, it has been done ). You create an object with alloc, new, copy or mutablecopy.
In this case, the dateFormatter gives you a new object but, since you did not call alloc, new or copy yourself, dateFormatter will call (normally its how it works) autorealease on the new NSDAte object.
But, if you were setting your property using the setter and getter, you would no have this problem.

NSDate init question, related to memory management in Objective-C

I have an NSDate object created by
NSDate *date = [[NSDate alloc] init];
Later, I want to reset the date to the "now", so I thought that
[date init];
or
date = [date init];
might do the job, but they don't. Instead,
[date release];
date = [[NSDate alloc] init];
works. I'm a bit confused about this, since in the documentation for - (id) init, it says:
Returns an NSDate object initialized to the current date and time.
and since date is already allocated, shouldn't it just need an init message?
Think of alloc and init as logically inseparable halves of a constructor. You can only call methods beginning with "init" once on a given object — once the object has been initialized, and it's an error to initialize it again. This is true for any Objective-C object, not just NSDate. However, NSDate objects are also immutable — once created, they can't change.
The reason the latter code works is because you're creating a new instance of NSDate, which is the correct thing to do. You can also use [NSDate date] to accomplish the same thing. Be aware that it returns an object that you don't (yet) own, so you'll need to retain it if you need to keep it around, and release it later.
Be aware that if you receive an object from someone, it has already been initialized. (If not, it's a programming error in the code that provided it, or is an extremely uncommon exception to the rule.)
If you want to get the current date you can just use:
NSDate * now = [NSDate date];
If you want to keep it then retain it.
NSDate * now = [[NSDate date] retain];
You can't reset NSDate with init, init is only for initializing the object for the first time.
You could just get another date:
NSDate * now = [[NSDate date] retain];
// use the now object
// need new date
[release now];
now = [[NSDate date] retain];
// once you don't need it release it
[now release];
The date message returns autoreleased instance of NSDate, hence the release or autorelease.
The autorelease is used for cases where you don't want to worry about where exactly you need to release the object - it is put into autorelease pool. Object in autorelease pool are released after the end of event loop iteration, or when you call release on pool ... (see more in Apple docs about memory management).
Btw. the [NSDate date] is a convenience method it's probably something like (not quaranteed to be exactly the same but functionally similar to):
- (NSDate *)date
{
return [[[NSDate alloc] init] autorelease];
}