Here is some code I have in my app that I DIDNT release. When I try to release I get a Program received signal: “EXC_BAD_ACCESS”. exception and the app crashes. If I dont try to release it the app runs fine.
Do I need to call a release message on these objects? Any idea what could be going on here?
NSString *sA = legA.text;
NSArray *firstLeg = [sA componentsSeparatedByString:#","];
[sA release]; //works ok
[firstLeg release]; //sends the bad access exception and crashes the app
Both of them don't need to be -released.
I suggest you read the Memory Management Rules. You need to -release an object if and only if the current scope is an owner of that object. You become an owner only when the object is received as
[[Foo alloc...] init...]
[foo new...]
[foo copy...] or [foo mutableCopy...]
[foo retain]
in all other cases, you should never -release it. As .text and -componentsSeparatedByString: are not one of these methods, there's no need to -release sA and firstLeg.
I'm not great at objective c, but shouldn't there be a [[NSArray alloc] init] thing somewhere? Or does the componentsSeperatedBySTring replace it?
No, you may only send release to objects you have ownership off: those you get from alloc/init, retain or copy.
Run, don't walk, to the "Object Ownership" section of the Memory Management Programming Guide for Cocoa and read up on the rules for when you "own" an object. You only release objects you own, so in this case you don't want to release them.
Several correct answers so far, but nobody has yet posted the Cocoa Memory Management Rules which should be compulsory when answering a "do I own this" question..
Edit: must type faster...
Related
I am a C programmer, but is pretty new to Objective-C. I've seen NSString-related code like this several times:
NSAppleScript* script = [[NSAppleScript alloc] initWithSource: #"<some script code>"];
...
[script release];
The above code explicitly releases the NSAppleScript object, but doesn't seem to release the NSString object anywhere.
I wondered if the [script release] automatically does the job of implicit release of the NSString object, so I changed the above code to the following:
NSString* scriptText = #"<some script code>";
NSAppleScript* script = [[NSAppleScript alloc] initWithSource: scriptText];
...
[script release];
//If [script release] has implicitly released scriptText,
//this would cause a repeated release.
[scriptText release];
But the above code turned out running also well. Does it mean that [script release] doesn't automatically release the NSObject object? In other words, does the code in the first section leak release of the NSString?
Very short answer: no. You shouldn't release scriptText. (In fact, you must not.)
In ObjC manual reference counting, you need to follow the rules, which are based on method names. If you call a method whose name begins with alloc or new or includes copy, then you are responsible for calling release or autorelease on the object that is returned to you. Also, if you call retain on an object, you are responsible to call release or autorelease.
Following the rules, you called +[NSAppleScript alloc], so you are responsible for calling release on the object returned to you. You did not call a retaining method to get scriptText; you used an NSString literal (#"..."). So you must not call release on it. It doesn't leak. (If it did, it would indicate a bug in Apple's code.)
The way this actually works is that NSString literals are stored directly in the binary, just like in C. There is no need to manage them, since they do not directly use memory. But this has nothing to do with your obligations under manual reference counting. You shouldn't think "this is a string literal so I shouldn't call release on it." That's not true at all. You should call release when the rules tell you to call release. It is completely correct to call retain on a value that happens to be a literal, and later call release on it. (This happens all the time. You generally don't know whether the NSString you're working with is a literal or not.)
It happens to be true that calling retain or release on NSString literals does nothing. They just ignore the call. Very short NSString objects don't even exist in memory. If they're short enough, the data is stored directly in the pointer (called a "tagged pointer"). Again, this is just an implementation detail. Your job is to follow the rules, not try to second-guess the system.
(The reason that your incorrect code with the extra release "works" is because literal NSStrings ignore memory management calls. The code is still incorrect. There's also no promise that over-releasing an object will cause a crash in any case, and it is very, very common when it does crash for it to occur at a random point, far away from the mistake. It's very common for objects to have pending autorelease calls on them, so you get a crash when the pool drains, with no hint where your bug is.)
And of course you should turn on ARC and let it handle it for you. It does a very good job. But it's helpful to understand the rules anyway. ARC uses the same name-based rules to figure out where to put retains and releases. That's how it can interoperate seamlessly with manual memory management.
I have this basic question where when we try to allocate memory to a string by using alloc init and add it to autorelease pool, and then try to release it, it doesn't crash.
NSString *value = [[[NSString alloc] initWithString:#"Hello"] autorelease];
[value release];
If I do the same thing for a array, it crashes.
I just want to know how string is different from array since both inherit from NSObject.
Do you mean it doesn't crash right away?
I.e. in the debugger after stepping over the release line?
The Autorelease-Pool will not have triggered at that point so the auto-release operation is still outstanding.
Either way - As always with memory errors they might not crash
instantly,
on your machine/operating system,
with this specific built,
with your current build settings,
...
or even at all.
It's a programming error nevertheless.
It is not guaranteed that the program crashes. Unfortunally there are several errors that does not cause a crash (immediately).
However there is an optimization for string literals. They live eternally regardless of the way they are created, retained or released. -initWithString: can be smart enough not to return a new instance of NSString.
First, undefined behavior is undefined -- it is not guaranteed to crash or do any other specific thing. Over-release is undefined behavior.
Second, what is happening here is that string literals evaluate to a pointer to a statically-allocated string object which lives for the lifetime of the program. It is not dynamically-allocated, and thus is not subject to memory management. retain, release, etc. have no effect on it. [[NSString alloc] initWithString:...] (as well as [... copy]) on an immutable string object simply retains and returns its argument directly, since there is no need to create a new object. So [[NSString alloc] initWithString:#"Hello"] is the same as #"Hello".
I'm currently profiling my app and coming across a few leaks. I've tried releasing objects all over the place where I think they are needed. Each release has crashed the app.
Here's one line that I think is the culprit:
NSDictionary *dicUserData = [NSDictionary dictionaryWithObject:self forKey:#"chapter"];
Just wondering the best way to deal with this. I'm having issues with other leaks too that are kind of similar. It's worth noting that self is a custom class [Dal_Chapter].
Do I need to implement copy or something, call that in the above line and do autorelease on that?
Thanks in advance.
Using convenience methods such as dictionaryWithObject provide an autoreleased instance of the dictionary object. Unless you're retaining it elsewhere this is not where your leak is.
I would check out the static analyser it should be able to point out your leaks for you.
That dictionary will retain self so you shouldn't have to worry about it.
Is the owner of self releasing it ?
Basicly you don't have to do anything whith your dictionnary, but if you want to take control of the memory you'll need to do this :
NSDictionary *dicUserData = [[NSDictionary alloc] initWithObjects:yourObject forKeys:key];
and int your dealloc method,
[dicUserDate release];
But normaly you just have nothing to do... Are you sure that your leak come from your dictionnary ?
always keep all variables release in dealloc method. is it not in proper place it may be crash .check this link click here
I have Util class as follows.
#implementation Util
- (NSString*) getTodayString
{
NSDate *today = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
// display in 12HR/24HR (i.e. 11:25PM or 23:25) format according to User Settings
[dateFormatter setDateFormat:#"YYYY/MM/dd"];
NSString *now = [dateFormatter stringFromDate:today];
[dateFormatter release]; ///???
[today release]; //???
return now;
}
#end
And I use the class
- (void)awakeFromNib
{
Util *ut = [[Util alloc] init];
NSString* now = [ut getTodayString];
NSLog(#"User's current time in their preference format:%#",now);
[currentTime setObjectValue:now];
[now release]; ///???
[ut release];
}
I'm confused when releasing objects.
In getTodayString ::
Q1. [dataFormatter release] is necessary?
Q2. [today release] is necessary?
I guess I don't need to release them as I didn't alloc myself. If that's true, when those objects are released?
In awakeFromNib ::
Q3. [ut release] is necessary?
Q4. [now release] is necessary?
I guess I have to release ut as I create the object explicitly, but not suer about now object.
How one can determine when is the object is released?
With python/C#/Java one doesn't care about this kind of deallocation of memory anymore. Is it also OK with Objective-C if I don't care about them?
Q1. [dataFormatter release] is
necessary? Q2. [today release] is
necessary?
dataFormatter: yes, you alloc/init'd it.
today: no, it was returned autoreleased from a factory method.
Q3. [ut release] is necessary? Q4.
[now release] is necessary?
The same,
ut: yes, you alloc/init'd it.
now: no, it was returned autoreleased from a factory method.
How one can determine when is the
object is released?
it's released when release is called on it, if autorelease is called, release will be called during the next run of the Autorelease Pool.
Is it also OK with Objective-C if I
don't care about them?
No, it's not ok. If you do not clean up after yourself you will have substantial memory leaks, in the iOS environment that means a quite shutdown of your app. In a Mac app that can lead to eating up a ton of memory and not being a good citizen. This is assuming a non garbage collection environment. Ie most.
I'm guessing the heart of your question is you aren't sure when you are responsible for calling release and when you get an autoreleased object (or rather, when you are responsible for calling release on the object). It's by convention. If you call any method that returns an object that does not contain the words: init/copy then it is not your responsibility to call release. If you retain, you release (There may be some more rules to follow, but that's the first one to really start understanding this, in my opinion). If you ever call alloc/init/copy, then you must call release at some point.
A GREAT teacher is Build & Analyze in Xcode. This will quickly point out where you screwed up and really help to understand what is going on.
Whether or not you care about memory management in objective-c depends on the environment you are using. If you are using garbage collection, you don't have to worry about it, but garbage collection is not enabled by default on the mac and is not available at all on iOS. Basic rules for when something needs to be released:
If the method you get it from starts with alloc or init, or contains the word copy, then you own it and must release it.
If you explicitly retain an object, you own it and must release it.
If the method does not contain alloc, init, or copy, you can assume it has been autoreleased. It will be released automatically at some point in the future, and you need to retain it if you want to use it after the current method returns.
Of course those also depend on any third party code following those rules with when they autorelease returned objects.
The memory management rules are simple and clear. Do not think in terms of retain counts, always think in terms of ownership. When you ask yourself the question “should I release this object?”, ask yourself “do I own it?”. Commit the rules to memory, and eventually they will become second nature.
It is extremely important that you follow the rules. If you ignore them, objects that you don't own may be deallocated before you are done with them (such as assigning objects that you don't own to instance variables, they may become deallocated after the autorelease pool is drained). Also, if you ignore them, you will end up with horrendous memory leaks.
If I do something like
address = [[NSString alloc] initWithData:addressData encoding:NSASCIIStringEncoding];
Then I know that I need to do like [address release] after I am done with using it.
Because "alloc" increases the reference count of "address" variable so that I need to do
[address release]
But I am not sure that I need to release if I do something like
NSData *addressData = [NSData dataWithBytes:buf length:address_len];
I don't see any "alloc" in this statement..So do I still need to do [addressData release] after I am done with this?
Thanks in advance...
No, you don't. You only need to release (or autorelease) an object if the method you got the object from is alloc, contains the word copy, or if you've retained the object.
Nope. In this case you can safely assume that the memory is autoreleased.
All explained in the Memory Management Ownership Policy
You do not need to do the release in your second example. The general rule is that you are responsible for a release if you call alloc, retain, or copy.
No, there is no need to release in your second statement. If you alloc, copy, new, then you should release the objects.
Objective C Memory Management for Lazy People has very useful info as to when to release objects.