Here i used auto-release for 'tempString' in the method 'test'. According to the rule, i should use "[temp retain]" in the main . But i didnt use it. still it works fine and prints the output. Then what is the need of "retain"? Can anyone pls tell me the reason? Thanks in advance.
-(NSMutableString *) test : (NSMutableString *) aString{
NSMutableString *tempString=[NSMutableString stringWithString:aString];
[tempString appendString:#" World"];
return tempString;}
int main (){
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
MemoryMgmt *memoryMgmt=[[MemoryMgmt alloc] init ];
NSMutableString *str1 =#"Hello";
NSMutableString *temp = [memoryMgmt test: str1];
NSLog(#" %#",temp);
[pool drain];
return 0;
}
stringwithString should return an autoreleased NSMutableString, but that doesn't actually get released until the NSAutoReleasePool drains. You are using the object while the pool is still retaining it and only draining the pool afterwards, releasing the object.
When you receive an autoreleased object from somewhere, you should only retain it if you intent to keep track of the object beyond the current variable scope. If you were to retain the object, but your reference were to go out of scope (as it does after your current function call completes), you would leak the object.
What you are doing here is actually correct, since you don't keep the reference to temp anywhere but in your local scope.
When you auto-release an object it will release at the end of the run-loop when the pool is drained or released...In your case, since you start a new thread, you manage the autorelease pool, the string temp does not release until you drain your pool, therefore when you use it, it is still valid...hope that helps
That works because the Autorelease pool doesn't get emptied until the end of the tool's execution. However, it is in fact correct usage: you return an autoreleased object from a method that doesn't claim to be passing ownership to the caller. Some people do
return [[tempString retain] autorelease];
Related
Please clarify the following thing.
Everyone knows that; if we are using alloc, retain, new and etc..., we have to release it. For remaining things, we have to use autorelease. My doubt is;
-(NSArray*)getArray{
NSArray *array = [[NSArray alloc] initWithObjects:#"1", #"2", #"3", #"4", #"5", nil];
return [array autorelease];
}
NSArray *arr = [self getArray];
---
---
What we have to do the arr?
EDIT:
NSString *str = [NSString stringWithFormat:#"Welcome..."];
If we are using the above statement, we should call autorelease. But I want to know, what is happening in the stringWithFormat:method. How it is returning NSString.
Thanks.
If you are planning to return the array, go ahead and use the [NSArray arrayWithObjects:#"1", #"2", etc, nil] instead.
You then just need to remember to retain it if you want to hold on to it for longer then the autorelease pool will hold it.
The autorelease pool will give it a retain count of 1, and then automatically decrement it by 1 when the release pool gets called. Without retaining it in the calling function, this object will eventually disappear.
You don't have to do anything with arr since you didn't explicitly alloc, copy, new, or retain it in its current scope. It's already been added to the autorelease pool so it'll automatically be cleaned up once you're done with it.
EDIT: In your edited question, [NSString stringWithFormat:] returns an autoreleased string. It's basically doing the same thing as you're doing in your getArray method. It builds a NSString (or related) object and autoreleases it before it's returned.
You should retain:
[[self getArray] retain];
Or return non-autoreleased object in getArray.
Your getArray method is returning an NSArray that _will_be_ released when the stack fully unwinds.
In the method where you are calling your getArray method, it is safe to use the NSArray, but if you want to keep it, and use it after your current method returns, you will need to retain the NSArray with [arr retain].
Answer to your new question
Class methods, like [NSString stringWithFormat:] or like [NSURL URLWithString:] return objects that have been autoreleased. This is a convention, a standard practice in UIKit and the Apple frameworks.
I am just reading through the Practical Memory Management guide.
I am somewhat confused by this block of code:
- (void)printHello {
NSString *string;
string = [NSString stringWithFormat:#"Hello"];
NSLog(#"%#", string);
}
It seems to me that string is going to have a reference count of 0. Is this true?
What stops string from being deallocated before we call NSLog(string)?
Is this somehow equivalent to this:
- (void)printHello {
NSString *string;
string = [[[NSString stringWithFormat:#"Hello"] retain] autorelease];
NSLog(#"%#", string);
}
Edit: Similarly this code is given in the Practical Memory Management
guide:
- (NSString *)fullName {
NSString *string = [NSString stringWithFormat:#"%# %#", firstName, lastName];
return string;
}
When and how does the return value get freed? Who is the owner? Does the caller of fullName need to release the string returned by full name?
Strictly speaking,
- (void)printHello {
NSString *string;
string = [NSString stringWithFormat:#"Hello"];
NSLog(#"%#", string);
}
Is not equivalent to
- (void)printHello {
NSString *string;
string = [[[NSString stringWithFormat:#"Hello"] retain] autorelease];
NSLog(#"%#", string);
}
The convention is that a method should autorelease any object it returns. The only exception (AFAIK) is for constructors, which return an object with a +1 retain count. Since [NSString stringWithFormat:] returns an object. In first snippet, stringWithFormat: returns an already autoreleased object. the second snippet, you're retaining it once more and it'll be released twice (which has the same effect, but the second retain/autorelease pair is redundant).
Ok, now to answer your question. Essentially, every time UIKit calls your code, it creates an NSAutoreleasePool object. Every time you autorelease an object, its added to this pool. Finally, when your code returns back to UIKit, it calls the drain method on the pool (i.e [pool drain]) and that releases every object which has been added to the pool and deallocates the pool. Also, autorelease pools can be nested, so you can create your own pools and drain them if you're going to be creating a lot of autoreleased objects. It isn't as complicated as it sounds.
I'd highly recommend that you read the Autorelease Pools chapter in the Memory Management Guide (Which incidentally, comes right after the Practical Memory Management chapter).
First of all:
NSLog(string);
Don’t do this. (I just realized it comes right from the Apple docs. Weird.) The first argument to NSLog is the formatting string. If your string contains some percent escapes, bad things will happen. The correct, if slightly longer way is:
NSLog(#"%#", string);
Now to the point: Autoreleased objects do not have zero retain count. They have retain count 1+ and have a pending –1 operation on them that will happen “soon in the future”.
The precise meaning of “soon in the future” depends on the situation. If you’re on the main thread and there is no additional autorelease pool in place, autoreleased objects will be released on the next runloop iteration. This does not have to be the case if you have an additional release pool:
// Let’s pretend this is a long loop and you don’t want to wait
// for the autoreleased objects to be collected by the main pool.
for (…) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *foo = [NSString stringWith…];
[pool drain];
// Now foo is no longer valid.
}
As for returning autoreleased objects, that’s one of the main use cases for autoreleasing. You are returning an object that will perish “soon”, but if the caller is interested, he can retain and take over the ownership. (It’s like, if you pardon the image, passing a bomb with a burning safety fuse. If the caller is interested, he’ll put out the fuse by retaining.) And if the caller is not interested, like maybe he’s ignoring an output from a function or just uses the value to construct some other object, he does not do anything and the object will get out of memory:
- (id) createObject {
return [NSString stringWith…];
}
- (void) interestedCaller {
NSString *value = [[self createObject] retain];
}
- (void) notInterestedCaller {
[self createObject]; // maybe just interested in side effects
NSString *differentString = [NSString stringWithString:[self createObject]];
}
This is really convenient and makes the manual memory management quite pleasant. You might be interested in run loops and the Objective-C tutorial by Scott Stevenson.
I've been reading about autoreleasepool but there is a point which is a bit unclear to me. I have some functionality using threads that required seperate memory managment using autoreleasepool.
In the following example is correct
-(void) doSomething {
NSAutorelease *pool = [[NSAutorelasepool alloc] init];
NSString *myString = #"Hello";
[pool release];
}
Is this correct?
-(void) doSomething {
NSAutorelease *pool = [[NSAutorelasepool alloc] init];
NSString *myString = [[NSString alloc] initWithString:#"Hello"];
[pool release];
}
or this?
-(void) doSomething {
NSAutorelease *pool = [[NSAutorelasepool alloc] init];
NSString *myString = [[NSString alloc] initWithString:#"Hello"];
[myString release];
[pool release];
}
My question is owned objects created in the scope of the autorelease pool need to be relased specifically or are the taken care of when the autorelasepool is been released?
Teo
Autorelease pool handles the autoreleased objects. If you own an object (via alloc or copy or retain) then you must release it. So your 2nd example is not correct. As you have allocated the string, you own it and you must release it.
An autorelease pool is created for the main thread. (You can look into the main function if you want). Every thread need its own autorelease pool to manage autoreleased objects. That's why if you create another thread then you must create an autorelease pool for that thread. Even if you don't create autoreleased object in the thread, you should create this as the library calls in that thread may create autoreleased objects. Even if you are sure that no library calls are making autoreleased objects then you also should create them as that is the best practice, specially if you are working on big project which is developed and maintained by multiple people.
You only need to create your own autorelease pool when you are creating a bunch of
autoreleased objects you want to garbage collect immediately. However, you are correct in that you don't want to reference any "autoreleased" objects you create after you release the pool. Autoreleased objects (which you don't retain) are destroyed when the pool is drained.
Since none of the objects in your example are autoreleased, creating your own autorelease pool is essentially a no-op.
Neither of your examples needs an autorelease pool. Autorelease pools only take care of autoreleased objects:
NSArray *foo = [NSArray array];
NSObject *bar = [[[NSObject alloc] init] autorelease];
Your first string is initialized using a string literal and therefore is probably special with respect to memory management (maybe someone else knows more). Your second string leaks, the pool does not make a difference. Your third string is released correctly, again the pool does not make a difference.
This is where you would need a pool:
- (void) someMethodThatRunsOnAThread {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *foo = [#"foo" uppercaseString];
[pool drain];
}
Here the foo string would leak if the pool wasn’t there. Note that I’m calling drain instead of release on the pool – on iOS there’s not a difference, but in garbage-collected environments the two differ, so it’s probably better to get in the habit of calling the right one.
Also note that you may need a pool even though you don’t autorelease any objects yourself, there could be many memory operations done somewhere in the code you’re calling in your method.
Think that this should be something like this:
-(void) doSomething {
NSAutorelease *pool = [[NSAutorelasepool alloc] init];
NSString *myString = [[[NSString alloc] initWithString:#"Hello"] autorelease];
// or create string like this (automatically autoreleased)
NSString *myString = [NSString stringWithString:#"Hello"];
[pool release];
}
You must send autorelease message, to objects inside autorelease pool. They will be released when release message is sent to pool.
I have this userInputstring in the header that will be modified and used by multiple methods in the .m file
.h
NSString *userInputString;
-(void)main;
-(void)method1;
-(void)method2;
.m
-(void)main{
[self method1];
[self method2];
}
-(void)method1{
NSString *localString = #"something";
userInputString = localString;
//do something else with it
}
-(void)method2{
NSString *localString = [NSString stringWithFormat:#"%# insert something",userInputString];
userInputString = localString;
[someOtherMethod:userInputString];//Crash
}
but I kept getting memory leak problems. What's the proper way to set it up? Im new to objective c.
I don't know where or how to release
Right, you first need to familiarise yourself with the Cocoa Memory Management Rules.
In summary, if you obtain an object by alloc, a method containing "copy", a method starting with "new" or if you retain it, you need to release or autorelease.
Take method1:
-(void)method1{
userInputString = #"something";
}
userInputString was not obtained with alloc, new or copy, nor have you retained it. Therefore you do not own it so you must not release it. If you had done this:
userInputString = [#"foo" copy];
or this:
userInputString = [[NSString alloc] initWithString: #"foo"];
or this:
userInputString = [#"foo" retain];
you do own the string therefore you must release or autorelease it.
When you release it depends on its scope. If it's a local variable, you must release or autorelease it before the block it is declared in exits. If it is an instance variable, you must release it before the object it is in is deallocated. i.e. you must release it in the dealloc method for the object. In all cases, if you overwrite an object you own, you must release it first. So:
userInputString = [someOtherString copy]; // you own userInputString
// do some stuff
[userInputString release]; // you no longer own it
userInputString = [someOtherString retain];// overwrite the pointeer with something else
This is one of the reasons for adding getters and setters for instance variables. Every time you set a new value, you have to release the old value and retain the new value (making sure that the old bvalue and new value are different), so this is encapsulated in the setter. A synthesized property adds this code automatically.
Try to use autorelease pool:
int main()
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
....
// Your code here
[pool drain]
return 0;
}
#"blablabl" is a shorthand to create an autoreleased NSString from a constant string. If if you don't have an autorelease pool in the thread you are running, those NSString object won't ever be released and of course your create a leak.
Either create an autorelease pool as Sumai suggest or release those objet's memory yourself. (tip: create an NSAutorelesePool ;-) )
Whenever I read about how to avoid memory leaks, I always came across a concept that
"Number of alloc must be equal to number of release".
But I came across a concept where we require more than one release. Like What I used to practise was as follows:
(NSString*) func1
{
NSString* result = [[NSString alloc] initWithFormat:#"Test String"]];
return result;
}
(void) func2
{
NSString* temp = [self func1];
[temp release];
}
But I came across a concept of retain count which says that in the above case the memory is not deallocated for the string since the retain count for the string is 1 at the end. So the right practise is
(NSString*) func1
{
NSString* result = [[NSString alloc] initWithFormat:#"Test String"]];
[result autorelease];
return result;
}
(void) func2
{
NSString* temp = [self func1];
[temp release];
}
So now I have two releases for deallocating the memory which is a contradictory to my above sentence which I read on most of the blogs ""Number of alloc must be equal to number of release".
I am little bit confused about the above stuff. Becoz if I autorelease the string in the first function and want to use the string in second function for a long time, and what if the release pool is flushed in between, on the other side if I dont use autorelease it will still block the memory.
So whats the correct way of doing it.
At the time you call alloc whatever is returned will have a retainCount of 1. Calling release on that object will cause it to be deallocated (it's retainCount will drop to 0). In your first example, then, the second line of func2 will deallocate the NSString* you received from func1, and your memory management chores are complete.
In the second example you are tossing result in func1 into the current autorelease pool, which will cause it to become deallocated when the pool drains. You do not want to attempt to manage the memory of that object once it has been placed into the pool- it is no longer your responsibility.
If you want to generate the string and keep it around for a while (e.g., through the lifetime of several autorelease pools), I would recommend the first form of memory management.
The correct way is this:
(NSString*) func1 {
NSString* result = [[NSString alloc] initWithFormat:#"Test String"];
// retaincount == 1
return [result autorelease];
}
(void) func2 {
NSString* temp = [self func1];
// retaincount == 1
// temp is autoreleased, therefore no [release] is necessary.
}
Autorelease is automatically done at the end of the run loop, that means it cannot be emptied while your code is doing something. -> The code you have is safe. This isn't true for multithreaded application!
(NSString*) func1
{
NSString* result = [[NSString alloc] initWithFormat:#"Test String"]];
return result;
}
[result retainCount] is 1
(void) func2
{
NSString* temp = [self func1];
[temp release];
}
[temp retainCount] is 0
No need for autorelease.
From Memory Management Rules:
This is the fundamental rule:
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.
The following rules derive from the fundamental rule, or cope with edge cases:
As a corollary of the fundamental rule, if you need to store a received object as a property in an instance variable, you must retain or copy it. (This is not true for weak references, described at “Weak References to Objects,” but these are typically rare.)
A received object is normally guaranteed to remain valid within the method it was received in (exceptions include multithreaded applications and some Distributed Objects situations, although you must also take care if you modify the object from which you received the object). That method may also safely return the object to its invoker.
Use retain in combination with release or autorelease when needed to prevent an object from being invalidated as a normal side-effect of a message (see “Validity of Shared Objects”).
autorelease just means “send a release message later” (for some definition of later—see “Autorelease Pools”).
In general, I'd feel safer to do a retain on a return value, like the one in the "func 2":
(NSString*) func1 {
NSString* result = [[NSString alloc] initWithFormat:#"Test String"];
return [result autorelease];
}
(void) func2 {
NSString* temp = [[self func1] retain];
// Do something with temp
[temp release];
}
Is this unnecessary? I understand that in this example "temp" is just a local variable. But it could have been an instance variable, which may need to be retained.