The mysteries of Objective-C plague me yet again.
I have a string. It's defined in a header file called "Common.h".
If I give it a value thusly:
_DATESTRING = #"2011-08-16";
There is no problem, and it sticks around forever, however, if I do this:
_DATESTRING = [format stringFromDate:[NSDATE dateWithTimeIntervalSinceNow:0]];
I get a "message sent to deallocated instance" further down the pipes.
Why?
// This is a string that's not going to be released
_DATESTRING = #"2011-08-16";
// This is a string that's autoreleased
_DATESTRING = [format stringFromDate:[NSDATE dateWithTimeIntervalSinceNow:0]];
// You want somethhing like this
_DATESTRING = [[format stringFromDate:[NSDATE dateWithTimeIntervalSinceNow:0]] retain];
In short, if your method name contains alloc, copy, new or mutableCopy you have to release it yourself. Otherwise it's already autoreleased so if you want to keep it around you need to retain it.
Where exactly is down the pipes?
The method stringFromDate: returns an autorelease object, so I'm quite sure that it's getting automatically deallocated when you want to use it. It doesn't happens with string literals because these do not follow the standard memory management conventions for objects.
You may want to add a retain message:
_DATESTRING = [[format stringFromDate:
[NSDATE dateWithTimeIntervalSinceNow:0]] retain];
because -stringFromDate: returns autoreleased object. If you want it to stick around forever, you need to send -retain message to it, that is:
_DATESTRING = [[format stringFromDate:[NSDATE dateWithTimeIntervalSinceNow:0]] retain];
Related
I have an allocated object where its attributes are store in the following memory places:
When I make a simple attribution of the NSDate attribute to a variable it gives me an EXEC_BAD_ACESS.
As you can see from the first image only the date attribute and the fileDate variable have different addresses.
Am I making some pointer related error?
The other 2 attributes are assigned correctly to the variables, it only happens with the NSDate so maybe I'm missing some detail about NSDate.
EDIT1
DownloadFile definition:
EDIT2
init function:
EDIT3
date parameter:
Is there any reason why you are not using ARC? There are quite a few memory management errors there causing leaks and one that should cause your crash.
NSDate *dateFromString = [dateFormatter dateFromString:receivedDate];
returns an autoreleased NSDate so when you then call the additional
[dateFromString autorelease];
you are overreleasing the NSDate hence your crash.
[pFile setDate:[[NSDate alloc] init]];
is a memory leak. Going through the setter setDate: will cause pFile to take a +1 retain on the date, which it should release in it's dealloc. The [[NSDate alloc] init] call returns a date object with +1 but is then never released elsewhere.
You can fix this either with
[NSDate date]
Or
[[[NSDate alloc] init] autorelease];
The first option is preferred
I realize this question may sound dumb, but just bear with me. I built an app to help new developers wrap their head around memory retention on the iPhone (no ARC yet). It is plain and simple, 4 buttons, init, access, retain, and release. Pretty self explanatory. I am displaying what the retain count for my string object that is the target of our poking and prodding. (Please no lectures on use of [myVar retainCount], I already know)
This stuff will never make it into actual apps, just toying with it for fun and hopefully help someone learn how memory works. My retain and release all work great. My question is that why does my retain count drop back to 1 if I call myString = [[NSMutableString alloc] init]; again. I can boost my retain count to 40, but after calling alloc/init I go back to zero. I am not leaking anywhere, just curious what happens to myString if/when alloc/init is called on it again.
My question is that why does my retain count drop back to 1 if I call
myString = [[NSMutableString alloc] init]; again?
Because you are failing to understand a very basic concept of Objective-C; myString is not an instance of an NSMutableString, but a reference to an instance. If you were to:
myString = [[NSMutableString alloc] init];
myString = [[NSMutableString alloc] init];
You now have two instances of NSMutableString, one leaked.
If you:
myString = [[NSMutableString alloc] init];
otherString = myString;
You now have a single instance of NSMutableString with two references.
In all three allocations, the NSMutableString instance will have a +1 retain count and, thus, you must balance each with a single release or you'll leak.
Treating retain counts as an absolute count is a path to madness. Or, at best, the scope of usefulness of the absolute retain count is so limited that learning about it is not applicable to real world iOS programming.
This bears repeating:
The retainCount of an object is tricky business.
If you were to continue down this path, you should be aware of the following details:
retainCount can never return 0
messaging a dangling pointer is not guaranteed to crash
retain count cannot be known once you have passed an object through any system API due to implementation details
any subclass of any system class may have an unknown retain count due to implementation details
retain count never reflects whether or not an object is autoreleased
autoreleases is effectively thread specific while the retain count is thread global
some classes are implemented with singletons some of the time (NSString, certain values of NSNumber)
the implementation details change from platform to platform and release to release
attempting to swizzle retain/release/autorelease won't work as some classes don't actually use those methods to maintain the retain count (implementation detail, changes per platform/release, etc..)
If you are going to teach retain/release, you should be treating the retain count as a delta and focus entirely on "If you increase the RC, you must decrease it".
when you call myString = [[NSMutableString alloc] init];, you're not "calling alloc/init on it again". You're not calling a method on the same instance you had. You're allocating and initializing a new instance, a completely different object from the one you had before.
And if you're doing that with a variable that had an object that you retained, then yes, you are leaking it.
Try this.
NSString *myString = [[NSMutableString alloc] init];
NSLog(#"%d", [myString retainCount]); // "1"
for (int i = 1; i < 40; i++)
[myString retain];
NSLog(#"%d", [myString retainCount]); // "40"
NSString *backup = myString;
myString = [[NSMutableString alloc] init];
NSLog(#"%d", [myString retainCount]); // "1"
NSLog(#"%d", [backup retainCount]); // "40"
You see, you have a different object with a new retain count. Your original object still exists and still has the same retain count. Assignment changes the object a variable refers to. A variable doesn't have a retain count, an object does.
myString = someOtherString;
NSLog(#"%d", [myString retainCount]); // who knows?
With retained property:
self.iString = backup;
NSLog(#"%d", [self.iString retainCount]); // "41" - 1 more because property retained
NSString *newString = [[NSMutableString alloc] init];
NSLog(#"%d", [newString retainCount]); // "1"
self.iString = newString;
// 1 for alloc 1 for retain (in real code you should release newString next)
NSLog(#"%d", [self.iString retainCount]); // "2"
NSLog(#"%d", [backup retainCount]); // "40" - self.iString released it
I have Question related to nsdate declaration.
NSDate *sortDate;
#property(nonatomic,retain) NSDate *sortDate;
#synthesize sortDate;
sortDate=[NSDate date];
I assign NSdate field in my class with above Procedure.I successfully assign value to my NSDATE(sortarray).Whaen when i retrieve its value's App craches with this message.
"malloc double free/non- aligned pointer being freed set a breakpoint in malloc_error_break to debug"
Give excess bad error.Some time it show,
When i remove NSDATE field from my class.App Run successfully.
Any thing wrong regarding declaration?
Any Solution.
Thanks in advance.
The date instance you get is autoreleased and not owned by you. If you assign directly to the ivar you have to take ownership, e.g.:
sortDate = [[NSDate date] retain];
It's usually better though to use the declared property, which takes care of that for you:
self.sortDate = [NSDate date];
Don't forget to relinquish ownership on dealloc, e.g.:
self.sortDate = nil;
See the Cocoa memory management rules and the declared properties documentation.
I try to get the last modification date of a file:
NSFileManager *fm = [[NSFileManager alloc] init];
NSError *err;
NSDate *lastModif = [[fm attributesOfItemAtPath:filename error:&err] objectForKey:NSFileModificationDate];//filename is ok ;-)
if(err == nil) {
[lastModif retain];
//I can put a NSLog of lastModif here, it works !!
NSTimeInterval lastModifDiff = [lastModif timeIntervalSinceNow];//crash here
}
I don't understand why the NSDate seems to be released, why the retain does not retain it.
Thank you if you have any idea...
You don't need to retain lastModif. I think you might be trying to treat lastModifDiff as an object of some sort when you do an NSLog with it or whatever you do with it afterwards. NSTimeInterval is a typedef to a double so you need to treat it as a double or [NSNumber numberWithDouble:lastModifDiff] if you want to use it like an object.
I'm having the same problem, but this post seemed germane:
NSDate : timeIntervalSinceNow crash
I'm writing a simple set of functions- startClock/endClock -using NSDate to determine FPS in my game loop. Except that timeIntervalSinceNow crashes, claiming that my earlier set NSDate object doesn't exist.
I know for a fact that the NSDate object has a retain count of 1 when I call startClock, but my theory is that NSDate instances are internally rigged to auto-release when they get bored and aren't feeling useful.
Using retain/release to assume ownership of these flighty and ephemeral NSDate objects worked for me.
SomeObject *temp = [[SomeObject alloc] init]
self.theObject = temp;
[temp release];
Why is it always done that way? Why not
self.theObject = [[SomeObject alloc] init];
If the theObject property is a retaining property, the first way is correct, because it doesn't leak memory. It's also more efficient than the correct way to write the second version, which is this:
self.theObject = [[[SomeObject alloc] init] autorelease];
Whenever you create an object with alloc you're in charge of releasing it somehow, whether by release or autorelease.
The second version leaks the SomeObject instance, since self.theObject will call a setter that, if properly written, retains the object.
You could just do
theObject = [[SomeObject alloc] init];
and some people certainly do. Others prefer to always use accessors though, either for consistence or to avoid bugs if the accessors have side effects (for exmaple, you would be bypassing KVO notification, which could be a problem if it's not part of an init method).