Suppose there is a string of type NSSTring
NSString *string;
There is array called testArray, which is array of string objects
string=[testArray objectAtIndex:1];
Do we need to give
[string release]
or not?
No, You needn't do
[string release]
You must release object only if you allocate memory for it. Check this Memory Management Policy for more detail information about alloc and release.
no .. in this case not.
if you get a string from a function, it has usually the autorelease flag and will get released later.
You need to release it if you retain it, if you alloc it or copy it.
You should read: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html#//apple_ref/doc/uid/20000994-BAJHFBGH
In this case you do not have to release the string. You only release the Objects which you own (created through alloc/init, copy or retain). Go through the memory management doc by Apple. In this case, testArray owns the string. Hence it takes care of releasing it when no longer required
No need to release. You have to release only the objects that you have allocated.
Only if you also called [string retain]. Otherwise the memory is managed by NSArray. you might call [string retain] if you need to remove it from the array, but still keep a reference to it.
Related
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".
This might be a stupid question, but it keeps bothering me.
Say if we have a method that takes an NSString object as its parameter and does something with the NSString object,
- (void)someMethod:(NSString *)str
{
//do something with str
}
Consider this code
[someObject someMethod:[[NSString alloc] initWithFormat:#"Hello World!"]];
Since alloc has been used in creating the string as parameter of someMethod, it has to be balanced by release no matter explicitly in pre-ARC environment or implicitly under ARC. But it seems there is no way we can get a pointer to the string as we have never assigned it to any pointer.
So my question is, first, is this way of passing parameter prohibited in writing objective c code? If no, then how objects created this way get released? And finally, does this code lead to memory leak?
Just for the record, I understand the above code is written
NSString *string = [[NSString alloc] initWithFormat:#"Hello World!"];
[someObject someMethod:string];
// [string release]; depending on ARC or non-ARC
Well, in fact, that object is assigned to the variable named str, which is a parameter of your method. You can manage the memory inside your method via that pointer, although methods aren't supposed to take ownership of their arguments (except see below).
ARC knows what to do in this situation -- it will either autorelease the object or add a release once the method is finished.
Under MRR, your snippet would be a leak; the correct way to avoid that is also to send autorelease:
[someObject someMethod:[[[NSString alloc] initWithFormat:#"Hello World!"] autorelease]];
or to use your last snippet (putting the string into a temporary variable and releasing later).
As a slightly esoteric option, it is possible for your method to declare that it owns the argument, by using the ns_consumed attribute:
- (void)someMethod:(NSString *) __attribute__((ns_consumed)) str;
This indicates that your method should send release to the object before it returns -- ARC will also take care of that.
So my question is, first, is this way of passing parameter prohibited in writing objective c code?
No. It's perfectly legal.
If no, then how objects created this way get released?
ARC will take care of it for you. If you do your own reference counting, then you can add it to the autorelease pool before it goes out of scope:
[someObject someMethod:
[[[NSString alloc] initWithFormat:#"Hello World!"] autorelease]];
^^^^^^^^^^^
And finally, does this code lead to memory leak?
Not in ARC. In MRC, you would need to add the -autorelease.
The static analyzer would also point out that leak.
There's no reason to not write code as you ask for consideration on… nothing prohibited in the slightest. These objects get released in the same manner that any other object gets released. Your lack of a variable to store the pointer in at the top level isn't important because the Objective C runtime knows about the object.
In a book, the following is said:
So how do you know when an object is owned, and by whom? Consider the
following example:
NSString *str = [[NSString alloc] initWithString:#”Hello”];
NSString *str2 = str;
In this example, you use the alloc keyword for str, so you own str.
Therefore, you need to release it when it’s no longer needed. However,
str2 is simply pointing to str, so you do not own str2, meaning you
need not release str2 when you are done using it.
I thought ownership is by object, not variable or pointer... so we can't say we "own str" or "own str2"... we own an object, which is pointed to by either str or str2, and if we use [str release] or [str2 release], it is all the same.
The other description is:
For example, consider the example used in the previous section:
NSString *str = [[NSString alloc] initWithString:#”Hello”];
NSString *str2 = str;
[str release];
[str2 release]; //---this is not OK as you do not own str2---
Attempting to release str2 will result in a runtime error because you
cannot release an object not owned by you.
We can actually use [str2 release] if that is called before [str release]. If we do that, then the line [str release] will cause an error because now str as well as str2 are both dangling pointers, and supposedly when release was sent to the object the first time, the reference count became 0, and dealloc was called immediately, and the memory was freed by the C function free().
Is the above correct, or maybe there is something else to be corrected?
Don't think of it in terms of managing memory, but in terms of object ownership. You obtain ownership of an object when you allocate it, retain it, or copy it. You are responsible for releasing exactly the objects you own, not others.
In your example the assignment to str2 does not take ownership of the object, but if you really need a second "owning" reference to it, then you ought to do [str2 retain], after which it is not an error to do [str release]; [str2 release];. This is also what would happen automatically using ARC, unless you annotated str2 as a weak reference. (Of course in this simple case the unnecessary retain/release could be optimized away internally by the compiler.)
Your guess is correct: The book uses fuzzy language (even though the implications are correct) in an effort to simplify pointers away:
You own the object that str and str2 point to.
This of course means that you can only release the object once (or rather however often it was retained - once in your example, implicitly, by alloc), and whether you do so through str or str2 (or any other means) is insignificant.
In practice, you should treat your variables as if you owned them, though. This makes it much easier to keep track of retain/release pairs, and you cannot rely on the fact that nobody changed the value of one of these variables somewhere in between.
It is good practice (but not necessary) to set all variables that point to a deallocated instance to nil afterwards.
To delve a bit into the technical details (which really should be treated as what they are: Implementation details; artifacts of a private API):
Technically, nobody owns the object. The object has a counter of the number of times it was retained (which you can find out by calling anObject retainCount - but you shouldn't, not least because some objects have a bogus retainCount, and because it's really none of your concern). When an object is alloced, its retainCount is 1. Every time it is sent retain ("it is retained"), its retainCount goes up by 1, and every time it is sent release ("it is released"), its retainCount is decreased by 1.
Once the retainCount of an object reaches zero, it is deallocated (and its dealloc method is called).
Who sent all those retain/release messages (and through which variables) is not important.
Again: These are implementation details. They're artifacts of the way Objective-C/Cocoa do their memory management. Treat them like any private API: It's good to be curious, but never rely on internals. Only ever use the public API (in this case, retain/release and autorelease pools) in production code.
NOTE: Some objects (for instance some singletons) override the default retain/release methods. Never trust the retainCount you get from an object, other than for curiosity (look at the retainCount of [UIColor clearColor] for instance).
For more thoughts on this topic, this question and its answers are probably a nice summary/starting point.
That said, consider switching to ARC, which will rid you of almost all memory management troubles.
I thought ownership is by object, not variable or pointer... so we
can't say we "own str" or "own str2"... we own an object, which is
pointed to by either str or str2, and if we use [str release] or [str2
release], it is all the same.
This is correct.
I think what the author means by "we own str" ist that you own that string instance. Not the pointer or the variable. You could theoretically release the object using an other pointer. But it's generally a better idea to release using the variable you used to initialize the object.
I think the other answers are wrong or incomplete.
Ownership is defined by who releases a resource. An object doesn’t (usually) own itself, it is owned.
Again: the owner is whoever is responsible for releasing the memory.
In your code, str has declared its ownership of the object, str2 has not. In order for str2 to also own the object (to share str’s ownership), you’d need to retain it:
[str2 retain];
Now you could later say,
[str2 release];
to relinquish str2’s claim to ownership, and the same goes for str.
On the other hand, with ARC, all (reference-counting) pointers to a resource are its shared owners. In this scenario, all pointers are responsible for keeping track of the object reference count, and releasing the object once they determine that they are the sole owners and go out of scope.
To reiterate: Ownership is not by object. Ownership is by pointers to an object, and the owner of those pointers, but only if those pointers might be released in some scenario. Pointers are non-owning if there is no scenario in which they would release the resource. In this case, they are called weak.
The concept of a weak pointer would make no sense if objects owned themselves (since all pointers would be weak).
If you release either str or str2, the memory location str and str2 points to is freed. So, you only have to call str or str2, not both, because they point to the same memory location.
I don't understand what you mean by 'owning' a variable, as far as I know a pointer can point to a piece of space in the memory, and nothing more.
I'm learning obj-c and I have a question about memory management:
Say I have a function that returns an NSDictionary, "fDictionary",
NSDictionary *fDictionary {
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:1], #"blah",nil];
return dict
}
that is called by a particular method:
-(int)fNumber {
NSDictionary *f = fDictionary();
return [[f objectForKey:#"blah"] intValue];
}
What I'm unclear about is how/where I should be releasing the NSDictionary object.
Should I release it in the method, or autorelease it in the function?
If the function was written properly, the dictionary is autoreleased, so you don't have to release it at all. It will be released soon, by the autorelease pool.
You only release what you yourself retain or copy. These are the things you "own". Be sure not to release them too early. The usual point is before the end of the function they are allocated or retained in, if they are local. If they are ivars, the best point is, usually, the dealloc of the class to which the ivar belongs.
Without knowing anything about fDictionary it's difficult to be sure, but the convention followed in most Object C code is as follows:
You own it if the instance was created with an alloc or copy
You own it if you retain it
Otherwise you don't own it
If you don't own it you should not release it.
So by convention, the function would return an autoreleased object and you wouldn't need any extra management in your method.
The general rule is if your code alloc's something, you need to release or auto-release it.
If this was someone else's function, you would expect that the returned dictionary was autoreleased - which is the convention here. I would ensure that fDictionary returns an autoreleased NSDictionary.
If you have received an object from a method which name begins with “alloc”, “new”, “copy”, or “mutableCopy”, you have to release or auto-release it. Otherwise it is already autoreleased.
If you have retained something, you have to release it, nothing else will do that for you.
Every Obj-C programmer must read Memory Management Guide.
No.
NSDictionary dictionaryWithObjectsAndKeys: (which is really just [[[NSDictonary alloc]initWithObjectsAndKeys:, nil]autorelease]) returns an autoreleased NSDictionary. This means the dictionary will automatically be released when the computer decides it is no longer needed.
If in fDictionary() the dictionary was alloced, you would need to release it manually. It is a rule of thumb to always return autoreleased objects from functions/methods, so the user of the functions/methods does not have to worry about memory management.
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.