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.
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'm new to Objective-C and cocoa. In the guide provided by Apple for Cocoa, there is a confusing example in memory management:
Suppose you want to implement a method to reset the counter. You have a couple of choices. The first implementation creates the NSNumber instance with alloc, so you balance that with a release.
- (void)reset {
NSNumber *zero = [[NSNumber alloc] initWithInteger:0];
[self setCount:zero];
[zero release];
}
The second uses a convenience constructor to create a new NSNumber object. There is therefore no need for retain or release messages
- (void)reset {
NSNumber *zero = [NSNumber numberWithInteger:0];
[self setCount:zero];
}
I am not sure why the object is created with 'new' instead of 'alloc & init' does not need to be retained/released. My understanding is that both are doing the same thing, except that with 'alloc & init' we can use custom checks and initialisation.
Many thanks.
The second example returns an auto released object. The code for the convenience constructor probably looks like this, at least when it comes to replicate the functionality.
+ (NSNumber *)numberWithInteger:(NSInteger)integer
{
NSNumber *number = [[NSNumber alloc] initWithInteger:integer];
return [number autorelease];
}
Autorelease is a way to defer sending a release method to an object while not delegating ownership of the object to the caller of the constructor. This is an important concept, because the naming conventions require you to not return ownership of an object unless your method starts with copy new alloc or retain. However, since you can't return an owned object, you would have to call release on it in your convenience constructor, which would then lead to you returning a deallocated object. So, autorelease allows you to return an un-owned object to the caller which will receive an actual release method later (when the current autorelease pool gets drained).
Autorelease methods are collected in so called autorelease pools, which are thread local quasi linked lists (they are not implemented as linked lists, but they do work like they were) and that just collect autoreleased objects. Objects can be added to them multiple times by calling, once for each autorelease method they receive. When the pools is drained or destroyed, all objects it contains will receive a release message. By default, the system will provide you with an auto release pool, at least on the main thread, but you can create your own ones using this code (which is also used in every main method, if you take a look):
#autoreleaspool
{
[foo autorelease]; // foo will receive a `release` method at the closing brace
}
By convention, all methods who's name start with "alloc" or "copy" or "new" increase the retain count by 1.
All other methods do not change the retain count. Since "numberWithInteger" doesn't start with "alloc" or "copy" or "new" it returns an object with a retain count of 0. But instead of setting it to 0 immediately (which would never work), it sets the retain count to 1 and then schedules it to be dropped down to 0 at some point in the future (usually when the event loop is idle, but you can manually make it happen sooner), using an "autorelease pool".
The only exception to the alloc/copy/new naming convention is, of course, the actual "retain" and "release" and "autorelease" methods, which increase/decrease the retain count or schedule it to be decreased later.
It is not a language feature, it's just a coding practice. Every method starting with "alloc" and "copy" and "new" sets retain to 1, everything else sets it to 1 but schedules it to be dropped to 0 later.
Of course, if you are using ARC, and you should absolutely be using ARC, then you don't have to worry about any of this because the compiler will find the last line of code that uses the object, and will insert a line of code after it to free up the memory. This leads to faster code, because the autorelease mechanism is a bit slow and sometimes uses too much RAM.
When ARC is enabled, none of those rules apply. The compiler ignores all your memory management code (or tells you to delete it), and writes it's own code. It's not actual garbage collection, it's just manual memory management that is generated by Xcode instead of written by hand.
Objects that are created with +alloc -init are returned with a retain count of +1, meaning that you have to call -release when you are done with this object. This is the same with +new , which is just a simple combination of [[ alloc] init], eg.
NSDate *date = [NSDate new]; // I will have to send -release at some point
As a convention, methods that contains init, new, create and copy will transfer ownership to you, meaning that you need to send -release at some point. Other methods will not transfer ownership, meaning that the object is autoreleased, ie. it has a short lifetime and is scheduled to be dealloced in the future. If you want this object to stick around, you will need to explicitly take ownership by sending -retain.
NSDate *date = [NSDate date]; // I won't have to send -release
// But this object will be dealloced soon
// so if I want it to stick around, I will need to retain it
This convention is not enforced by the language.
It is also useful to remember that this convention expands beyond the Objective-C part of the SDK, it is also the case in CoreGraphics and all C frameworks provided by Apple, and most third-party frameworks make use of this convention.
CGContextRef context = UIGraphicsGetCurrentContext(); // I won't have to release this context
CGImageRef result = CGBitmapContextCreateImage(context); // I will have to release this image
/* ... */
CGRelease(result);
As for your example : -numberWithInteger: does not contain either init, new, create or copy. So you don't need to -release it when done.
I have been going over some tutorials in Objective-C and I am confused when it comes to the command alloc() and how it is used to initialize an object.
The tutorial says to do the following and I am having trouble figuring out why it is necessary.
Change
NSDate *now = [NSDate date];
to
NSDate *now = [[NSDate alloc] init];
Why is this change necessary since the first line works just fine? I guess I am looking for how the two lines differ. Thanks!
There's a simple difference and a deeper one.
The simple answer is that the first method includes an +alloc/-init pair internally—the documentation tells us that it returns a new date object initialized to the current time. Generally, somewhere, somebody has to call +alloc and an -init method of some sort. Sometimes that's you, sometimes a convenience method has been included for you.
The deeper answer about the difference is that +alloc/-init returns an object that is owned by the caller, who is then responsible for calling -release at some point, while convenience constructors that don't start with the words "alloc" or "new" return autoreleased objects that you don't have to release. However, if you are using ARC, this is mostly academic, as the compiler tracks that detail for you.
Break it down:
NSDate is a class. So NSDate alloc is a call to the class method alloc. That's actually inherited from NSObject and acts to create sufficient storage for a new instance of NSDate, then return it for use as an instance.
(instance) init is a call to the instance method init. Prior to calling init the instance you've received is not guaranteed to be in a valid state. Calling init or the relevant initialiser gives the instance the chance to establish itself.
NSDate also choses to supply the class method date. That does the same thing as [[[NSDate alloc] init] autorelease] and is provided as a mere shorthand.
As other posters have commented, there is a semantic difference here — alloc returns an owning reference. So it's the caller's responsibility to release the object later. date returns a non-owning reference. So the caller has no responsibilities. However the modern ARC compiler will deal with releasing things for you. So there's a difference but not one that has any real effect on you.
If your tutorial insists that date is more proper then either it was written before the ARC compiler or was written by someone that prefers to use the old conventions; using date would traditionally communicate that the thing you were creating was for transient use so there is arguably some extra value in the one way versus the other for an experienced developer.
With ARC it doesn't matter as you no longer have to release objects you alloc init.
Without ARC the difference in important:
[NSDate date]
returns an autoreleased object using a class method on NSDate.
[[NSDate alloc] init]
returns a non autoreleased object instance, with a retain count of one.
As in non- ARC, you need to take memory management in your own hands, So, alloc init is better option. So, that you can release it, once not required.
One further point to note, is that autoreleased objects are released when the autorelease pool is.
When you alloc init you know that your object will stay around until you release it (or you leak it because it goes out of scope).
The change is not necessary at all. It doesn't matter if you create object using alloc+init or using convenience methods. Think about them as legacy and convenience methods.
I still have some unclear understand about release and autorelease. What are the difference between both of them? I have this code. For facebook connection. I crash it sometimes when I go to Facebook login, I doubting maybe it is because I don't release the object nicely.? Thanks for any helps
if (_session.isConnected) {
[_session logout];
} else {
FBLoginDialog* dialog = [[[FBLoginDialog alloc] initWithSession:_session] autorelease];
[dialog show];
}
The Memory Management Programming Guide for Cocoa will soon be your best friend. In brief, object instances in Cocoa are memory managed using reference counting (unless, of course you're using garbage collection on OS X). An object indicates that it wants to 'retain' an ownership interest in an other instance--keep it from being deallocated--by sending it a -retain message. An object indicates that it wants to release that interest by sending the other instance a -release message. If the number of objects that have 'retained' and ownership interest in an object drops to 0 (i.e. when the last of the owning instances sends a -release message), the instance with a 0 retain count is deallocated.
It's sometimes convenient to say "I want this instance to be released some time in the future". That's the purpose of -autorelease. Sending an -autorelease message adds the receiver to the current NSAutoreleasePool. When that pool is drained, it sends a -release message to all the instances in the pool. An NSAutoreleasePool is automatically created at the start of each iteration of each thread's run loop and drained at the end of that iteration. Thus, you can do something like this in a method:
- (id)myMethod {
return [[[MyObject alloc] init] autorelease];
}
The caller of this method will get back an instance that they can -retain if they wish to keep it. If they don't retain it, it will stick around at least until the enclosing autorelease pool is drained:
- (void)someOtherMethod {
...
id instance = [obj myMethod];
... // do more with instance, knowing that it won't be dealloc'd until after someOtherMethod returns
}
Releasing means you release that right away.
Autoreleasing means you want the variable to be released on the next autorelease pool.
You use autorelease when you want to keep retaining the variable but don't want to create a memory leak. You use release when you don't need the variable anymore.
Sample:
- (NSNumber *)return5 {
NSNumber * result = [[NSNumber alloc]initWitnInt: 5];
[result autorelease];
return result;
}
Why do we use autorelease there?
If we use [result release] instead, variable result will be destroyed AT that time. Which means that the returned value will be garbage.
If we do not release at all, variable result will be hold FOREVER incurring memory leak.
We can tell every caller to the function to release result but that would be a headache and prone to error.
So we use autorelease. We mark the variable to be released on the next autorelease pool. Basically we mark the variable to be released near the alloc. Hence the mantra alloc is paired with release in the same function holds all the time.
Actually, you'll do fine changing all release into autorelease. Your memory use won't be efficient, however, the effect is minimal. All variables, in all programming language is effectively autoreleased.
Anyway, use ARC.
background discussion:
objective-c is reference counted, so objects are deleted when the reference count reaches 0. release reduces the reference-count immediately, autorelease reduces it when the autorelease-pool is popped
when to use:
use autorelease when allocating the object if
you do not need it after the current function
it will be retiained by some other objet/function and will be released by a later by the retaining code
when the logic of the current function is tricky, so you would have to send release in a dozen different places before doing a return
use "manual" release
to revert a previous retain (in case you are implementing a library)
if you need precise control of freeing objects (e.g. they use lots of memory or the autorelease pool will not be popped for some time)
but really my freand:
read the Memory Management Programming Guide for Cocoa as suggested by Barry and run your code with instruments (zombies and leaks) often to catch any and almost all memory management errors.
Erik
According to the Memory Management Programming Guide for Cocoa:
The autorelease method, defined by
NSObject, marks the receiver for later
release. By autoreleasing an
object—that is, by sending it an
autorelease message—you declare that
you don't want to own the object
beyond the scope in which you sent
autorelease.
Also:
The autorelease method thus allows
every object to use other objects
without worrying about disposing of
them.
Here is the gist of some code I'm writing. I'm concerned that I am not properly addressing the retain/release issues with the array class method on NSMutableArray. Is the following actually leaking memory?
for(a while) {
// do stuff
NSMutableArray *a = nil;
// do stuff
if (!a) {
a = [NSMutableArray array];
}
} // for(a while)
You wouldn't leak memory in this code, and releasing the array yourself will cause a crash when the array is autoreleased at the end of the run loop.
Most Cocoa classes provide a couple of ways of making a new object, and are very consistent with this convention:
[[NSSomeObject alloc] init] : you are responsible for releasing the object (instance method).
[NSSomeObject someObject] : the object will be autoreleased for you, usually at the end of the run loop (class method). It's roughly equivalent to [[[NSSomeObject alloc] init] autorelease].
The proper use of the instance method would be:
a = [[NSMutableArray alloc] init];
// do stuff
[a release];
The proper use of the class method would be:
a = [NSMutableArray array];
// do stuff, array is in the autorelease pool
Note that Apple has recommended you stay away from the convenience methods as much as possible to improve performance. This is controversial advice, may not save much processor time, and separates the alloc-init from the release on an object you may not actually care much about keeping.
From the Cocoa Memory Managment Rules:
You take ownership of an object if you create it using a method whose name begins with “alloc” or “new” or contains “copy” (for example, alloc, newObject, or mutableCopy), or if you send it a retain message. You are responsible for relinquishing ownership of objects you own using release or autorelease. Any other time you receive an object, you must not release it.
Therefore with the line:
a = [NSMutableArray array];
you do not take ownership of the array, and it will be passed to you autoreleased. The memory will be handled for you automatically by the autorelease pool, and once it is no longer being used, it will be released for you. If you want to keep the array outside the current event, however, you must retain it, otherwise it will be released for you.
Yes, if you want it to stick around.
The returned object is an autoreleased object which will get deallocated when its autorelease pool gets purged.
All the array class methods that begin with "array" return these types of autoreleased objects.
Read this doc by Apple.
That's valid. It may help to just manage things manually when you have questions, to learn.
There is a convention:
init prefixes (init, initWithString:) indicate a retain count of 1, where
objectname prefixes (string, stringWithString:) indicates an autoreleased object
I have had the habit, for years, to release what I can at the call site, rather than pushing it to be autoreleased. Some autorelease issues then become painfully difficult to track down. Sure, autorelease is a convenience to the programmer in this case (provided nothing goes wrong), but adversely affects reuse, clarity, and performance (moreso in large codebases/programs).