I do apologize if this have been asked before but i have not found a good answer.
When i run the Instruments i get a leak on this line in the code, not in main:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
I have been looking around and read somewhere that it may be a bug. Could someone please help me and share some light on this?
I did notice that i have the same name, "pool", in main also.
The name doesn't matter; there may be hundreds of variables named pool throughout the codebase. What matters is scope.
Typically, you'll see this:
- someMethod
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
... do stuff ...
id something = [anObject retain];
[pool drain];
return [something autorelease];
}
I.e. is your pool being drained?
(drain exists on iOS; see the documentation. However, in all cases, it is better to use #autoreleasepool{ ... }; it works in ARC and MRR.)
I had this problem as well, my first problem on the first day learning how to code!
All I did was remove outright the entire line starting with:
NSAutoreleasepool *pool = [[NSAutoreleasepool alloc] init];
replace it with:
#autoreleasepool {
Then I deleted at the bottom of my program:
[pool release];
Then closed off with the squiggly brackets.
I don't know why it works, my first day remember but it runs my program from the example book fine.
Related
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.
I have this code:
NSNumber *num;
NSAutoreleasePool *apool = [[NSAutoreleasePool alloc] init];
for (int i=0; i<images_count; i++) {
num = [NSNumber numberWithInt:images_count];
[self performSelectorInBackground:#selector(loadData:) withObject:num];
}
[apool release];
[num release];
and it generates the following error:
2011-06-17 03:10:30.768 CHARLIE[2456:6c03] * __NSAutoreleaseNoPool(): Object 0x703d0f0 of class __NSArrayI autoreleased with no pool in place - just leaking
I don't understand why its leaking, can someone please explain how to fix this?
Thanks a lot,
Jack
There are a couple of issues with that code.
The lack of an autorelease pool is probably due to the loadData: method running without an autorelease pool.
The [num release] is nonsense.
Spawning a thread per every iteration of that loop is pretty much guaranteed to be the least performant possible approach to parallelizing image loading.
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.
I'm running some code in a background thread to get a text file from a service. That code fires a delegate at some point. It throws as SIGABRT error once the delegate is being called and well, my concept doesn't sound convincing to me either.
The code running at the background thread:
- (void)FetchStores
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Fetch from service
NSString *serviceURL = #"http://../index.html";
NSURL *myURL = [NSURL URLWithString:serviceURL];
NSData *dataRep = [NSData dataWithContentsOfURL:myURL];
storesList = [[Stores alloc] init];
storesList.storesDelegate = self;
[storesList FetchWithNSData:dataRep];
[pool release];
}
The storesList object will fire a delegate once all the stores have been extracted from the service. The delegate is getting caught by a function at the main thread.
Do you have any suggestions what am I doing wrong ?
Thank you,
f.
When calling the delegate, somewhere, you should make the switch to the main thread.
Especially if somewhere, you are updating the UI based on the data fetched.
You can use
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait
to make the switch.
Maybe like this:
storesList = [[Stores alloc] init];
storesList.storesDelegate = self;
[storesList performSelectorOnMainThread:#selector(FetchWithNSData:) withObject:dataRep waitUntilDone:TRUE];
In your case, you should use waitUntilDone:TRUE so that the FetchWithNSData method gets a chance to retain the data.
It seems quite likely that FetchWithNSData: does not retain the passed dataRep and the data gets deallocated on the next line where you drain the local autorelease pool?