If I use NSAutoreleasePool, every object created inside the pool should never be released mannually?It will be released when the pool is drained?
- (void) backgroundRequest{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
urlList = [[NSMutableArray alloc] init];
target = [[NSMutableArray alloc] init];
{
//do stuff in here
}
[urlList release];
[target release];
[pool release];
}
Are the above lines correct or I should remove [urlList release] and [target release]?
IMPORTANT: I will wait an explanantion and an answer.Thank you
An autorelease pool only works when you have objects using the Autorelease methods.
If you're using this:
urlList = [[NSMutableArray alloc] init];
Then you will want to do your own release, yes. However if you do this:
urlList = [[[NSMutableArray alloc] init] autorelease];
Then you can let the NSAutorelease pool handle that.
If you dont want to release urlList and target, then you can use this code:
- (void) backgroundRequest
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
urlList = [[[NSMutableArray alloc] init] autorelease];
target = [[[NSMutableArray alloc] init] autorelease];
{
//do stuff in here
}
[pool release];
}
Hope this helps you.
The point is that AutoreleasePool takes care of those allocations which have been autoreleased with the keyword autorelease So if you use that keyword then you don't need to release it. It is released when the AutoreleasePool gets released.
If you need more information then please leave me a message below.
I second the answer from #Brayden. I would like to add up to that.
Generally every thread has its autorelease pool. See your .main file for instance. It has got an autorelease pool associated with it. So that way your main thread has got an autorelease pool.
Now when you spawn another thread, ie try to run some methods on another thread, and if your gonna use class methods for common initialization.
eg: NSString *strTem = [NSString stringWithString:AnotherString];
Such is the case where autorelease will be used, and for such functions(methods) you need to have a separate autorelease pool of your own.
Hope this helps some more.
Related
Ok, so my question is something I have been looking for for a while. Say the method "first" has been detached as a new thread.
-(void)first{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int a;
NSMutableArray *array = [self getArray];
[pool drain];
}
-(NSMutableArray *)getArray{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSMutableArray *ar = [NSMutableArray array];
[ar addObject:[NSString stringWithString:#"Hello"]];
return ar;
[pool drain];
}
My issue is that if i drain the pool after the object is returned, the pool doesnt get drained, and its leaked, however if i drain it before i return the array i cannot release the array because obviously its going to be needed...
This may be something thats really obvious, and i'm just missing but i am really confused. Thanks in advance.
It is unnecessary to have a second autorelease pool in the getArray method.
If, for some reason, you wanted to have an ARP in the getArray method, you'd probably implement it like this:
- (NSMutableArray *)getArray {
NSMutableArray *ar = [NSMutableArray array];
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
//do stuff
[pool drain];
return ar;
}
You technically can leave the pool un-drained, and it will get drained automatically when a "higher" pool gets drained, but IMO that's a sign of some really poorly designed code.
I have a class
#implementation MyClass
- (void) foo
{
ivar = [NSString stringWithString:#"ivar"];
}
- (void) bar
{
NSLog(#"%#", ivar);
}
And main.m
MyClass * m = [[MyClass alloc] init];
[m foo];
[m bar];
Why no retain is needed for stringWithString?
Can you show me an example where retain is needed?
Its because the autorelease pool had no time to drain its content. Here is a crashing example:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
MyClass *m = [[MyClass alloc] init];
[m foo];
[pool drain];
[m bar];
The autorelease pool that holds the string in your example belongs to 99% to the current runloop which creates a new pool at the begin of the event loop and then drains it at the end.
Why no retain is needed for stringWithString?
Because the autorelease pool is not being drained between line 2 and line 3 (as it would be in a Cocoa app as soon as your code returns control to the run loop).
You can start by reading Memory Management Programming Guide and look at this tutorial.
Have a look at Memory Management Rules from Apple. In your case, you did not alloc/retain/net the NSString so you don't "own" it and therefore you do not need to release it.
Internally, NSString would return you a autoreleased object. If you don't retain it then you'll lose reference to it if it gets dealloced by an autorelease pool.
-(void) func1: (NSData*) somedata
{
//Processing somedata ....
[somedata release]; //is it necessay?
}
You shouldnt release somedata inside your method.
NSData *somedata = [[NSData alloc] init];
func1(somedata);
[somedata release];
Assumptions:
func1 runs on same thread
In this case, no, you should not release your object. You're not the "owner". As a rule of thumb, you need to release an object once you're done with it only if:
You allocated it via [MyClass alloc], as in [[MyClass alloc] init] or [[MyClass alloc] initWithFoo:foo bar:baz].
You got a copy via [someObject copy] or [someObject mutableCopy].
You have retained it before.
You should consider releasing it If you are retaining it in this case. But I am not sure because your question does not provide any idea whether a release is required or not. But generally you will release objects if you take ownership of it.
I want to get some memory leaks in my code, how can i fix the memory leak.
dashboard = [[NSMutableArray alloc] init];
[dashboard addObject:[[NSDictionary alloc] initWithObjectsAndKeys:#"demo_1.jpg",#"pic_source",#" Head",#"Title",nil]; // memory leaks here.
if ( theConnection ) {
receiveData = [[NSMutableData data] retain]; //memory leaks here.
}
But i have released dealloc - in[receiveData release];, but memory leaks happened. I know the retain, the count is increased, but how can i released the data properly.
Thanks!
i think your leak in the line:
[dashboard addObject:[[NSDictionary alloc] initWithObjectsAndKeys:#"demo_1.jpg",#"pic_source",#" Head",#"Title",nil];
just change it to
[dashboard addObject:[NSDictionary dictionaryWithObjectsAndKeys:#"demo_1.jpg",#"pic_source",#" Head",#"Title",nil];
addObject retains the object so you can use convenience creation methods which autorelease the object they create.
and another possible leak... if you define your receiveData as a property with retain attribute you don't need to call retain explicitely. You can call self.recieveData = [NSMutableData data]. This will retain it. Of course you will still need to release it in dealloc.
EDIT to show the code:
NSMutableArray *anArray = [[[NSMutableArray alloc] init] autorelease];
[sections setValue:anArray forKey:display_date];
dashboard addObject:[[NSDictionary alloc] initWithObjectsAndKeys:#"demo_1.jpg",#"pic_source",#" Head",#"Title",nil];
You've called init method - then you are the owner of an object. When you've put it to the array - the retain was called too. Just call autorelease to fix the leak.
receiveData = [[NSMutableData data] retain]; - if you will call release this object will be deleted when out of scope. If you will write
receiveData = [NSMutableData data];
It will be automatically deleted when out of scope
EDIT
If you are using methods with init word in them then you are the owner of such objects and they will not be deleted automatically until you'll call release method on them. If you don't want to own the object create it with some static method. For example:
NSMutableArray *array = [NSMutableArray arrayWithObjects: ... , nil];
It's the same as calling
NSMutableArray *array = [[[NSMutableArray alloc] initWithObjects: ... , nil] autorelease];
Autorelease means the object will receive a release method when out of scope - and if it was not retained will be deleted automatically
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.