I create a second thread to call a method that downloads several images using:
[NSThread detachNewThreadSelector:#selector(downloadImages) toTarget:self withObject:nil];
It works fine but I get a long list of leaks in the log similar to:
2010-04-18 00:48:12.287 FS Companion[11074:650f] *** _NSAutoreleaseNoPool(): Object 0xbec2640 of class NSCFString autoreleased with no pool in place - just leaking
Stack: (0xa58af 0xdb452 0x5e973 0x5e770 0x11d029 0x517fa 0x51708 0x85f2 0x3047d 0x30004 0x99481fbd 0x99481e42)
2010-04-18 00:48:12.288 FS Companion[11074:650f] *** _NSAutoreleaseNoPool(): Object 0xbe01510 of class NSCFString autoreleased with no pool in place - just leaking
Stack: (0xa58af 0xdb452 0x5e7a6 0x11d029 0x517fa 0x51708 0x85f2 0x3047d 0x30004 0x99481fbd 0x99481e42)
2010-04-18 00:48:12.289 FS Companion[11074:650f] *** _NSAutoreleaseNoPool(): Object 0xbde6720 of class NSCFString autoreleased with no pool in place - just leaking
Stack: (0xa58af 0xdb452 0x5ea73 0x5e7c2 0x11d029 0x517fa 0x51708 0x85f2 0x3047d 0x30004 0x99481fbd 0x99481e42)
Can someone help me understand the problem?
The error is "_NSAutoreleaseNoPool()". There is not an NSAutoreleasePool allocated by default in a thread. You need to create one yourself otherwise the -autorelease'd objects will be leaked.
Your -downloadImages therefore should look like this:
-(void)downloadImages {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
...
[pool drain];
}
I'm just on a similar issue... with funny nested threads leaking as hell.
Don't forget to release the pool too. :-)
-(void)downloadImages {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
...
[pool release];
pool =nil;
}
Related
When ever i am trying to update the UIActivityIndicatorView from thread . the app is getting crashed by throwing an exception
modifying layer that is being finalized - 0x7e177fd0
-[CALayer removeAnimationForKey:]: message sent to deallocated instance 0x7e177fd0 .
when i try track the memory leaks form the mallocDebugger tool .
this crash is not happening at all the time happening 1 out of 10
please help me out rom this memory issue
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
[autoRechargeCell addSubview:activityIndicator];
[self.activityIndicator startAnimating];
if( [PennyTalkAPI getBalanceInfoForAccount:appDelegate.accountNumber withPIN:appDelegate.pinNumber])
{
[autoRechargeCell.switchField setOn:[[NSUserDefaults standardUserDefaults] boolForKey:#"AutoRecharge"]];
[self.activityIndicator stopAnimating]; <<<<<<<<<<<<<<<<<<<<<<
}
else
{
[self.activityIndicator stopAnimating];
}
[pool release];
This is the code i have written
Without looking at code and seeing error I assume you release your Activity Indicator and then you are trying to access it to animate..
Solution: Declare UIActivityIndicator object in .h file synthesize and release it in -(void)dealloc method.
This is either a double release error, or a dangling pointer. You should enable zombie detection in your Scheme's configuration, and try the Zombies instrument in Instruments.
If I create a thread with a callback like..
NSAutoreleasePool* pool = [NSAutoreleasePool alloc] init];
while(1) {
//Process Stuff
}
[pool release];
I assume that anything autoreleased will never really be freed since the pool is never drained.
I could change things around to be like this:
while(1) {
NSAutoreleasePool* pool = [NSAutoreleasePool alloc] init];
//Process Stuff
[pool release];
}
But it seems a bit wasteful to alloc/delete so often. Is there a way I can set aside a block of memory and release the pool once its full?
Don't worry about it, because Autorelease is Fast. Your second option is fine. And in fact, in ARC, it will be hard to do anything besides those two options because of the new #autoreleasepool { } syntax.
If you allocate a significant* amount of autoreleased memory in each iteration of your loop, then creating and releasing a new pool for each iteration is the proper thing to do, to prevent the memory from piling up.
If you don't generate much autoreleased memory, then it wouldn't be beneficial and you will only need the outer pool.
If you allocate enough memory that a single iteration is insignificant, but there is a lot by the time you are done, then you could create and release the pool every X iterations.
#define IterationsPerPool 10
NSAutoreleasePool* pool = [NSAutoreleasePool new];
int x = 0;
while(1) {
//Process Stuff
if(++x == IterationsPerPool) {
x = 0;
[pool release];
pool = [NSAutoreleasePool new];
}
}
[pool release];
* You need to determine what significant is for yourself.
I have used the following code to create a new thread:
[NSThread detachNewThreadSelector:#selector(backgroundMethod:)
toTarget:self
withObject:paramObject];
And then in backgroundMethod I have set up a new autorelease pool as per usual:
-(void)backgroundMethod:(id)parameter
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
//method stuff here...
[pool drain];
}
But somehow the autorelease pool is not working. When running the code, the output in the console is as follows:
2011-02-17 00:38:16.928 audioEngine[13670:af03] *** __NSAutoreleaseNoPool(): Object
0x4b22370 of class NSThread autoreleased with no pool in place - just leaking
I have used multiple threads in the same way before and had no similar problem - what am I doing wrong?
Any help is much appreciated! Thanks :)
EDIT: Ok this seems a bit weird - I created an autorelease pool in the method that the new thread is created from, and the problem disappeared. Any idea as to why this might be and what the right way to fix it should be? I'd rather not have a random autorelease pool in my code without knowing what it's actually doing and why the problem is gone.
EDIT2: Here's the code creating the main autorelease pool:
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
It seems that it's complaining that the detachNewThreadSelector: call is the one that isn't being made with an autorelease pool in place, and not something within the backgroundMethod function, so that when the backgroundMethod finishes executing, the thread object is being leaked.
Check that the thread (main thread) that creates the background thread has an autorelease pool set up.
This is the body of the selector that is specified in NSThread +detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
while (doIt)
{
if (doItForSure)
{
NSLog(#"checking");
doItForSure = NO;
(void)gettimeofday(&start, NULL);
/*
do some stuff */
// the next line prints "_NSAutoreleaseNoPool():" message to the log
CGImageRef screenImage = UIGetScreenImage();
/*
do some other stuff */
(void)gettimeofday(&end, NULL);
elapsed = ((double)(end.tv_sec) + (double)(end.tv_usec) / 1000000) - ((double)(start.tv_sec) + (double)(start.tv_usec) / 1000000);
NSLog(#"Time elapsed: %e", elapsed);
[pool drain];
}
}
[pool release];
Even with the autorelease pool present, I get this printed to the log when I call UIGetScreenImage():
2010-05-03 11:39:04.588 ProjectName[763:5903] *** _NSAutoreleaseNoPool(): Object 0x15a2e0 of class NSCFNumber autoreleased with no pool in place - just leaking
Has anyone else seen this with UIGetScreenImage() on a separate thread?
[pool drain] on iOS behaves the same as [pool release]. So after the first iteration of your while loop you end up with having no autorelease pool in place. Remove the drain and you should be fine. Not sure whether it's OK to use UIGetScreenImage() in threads other than the main thread, though.
I have an iphone app project. I analysed it using instruments memory leak tool. According to instruments I have 2 leaks the Trace is as follows:
start main UIAplicationMain _run CFRunLoopInMode CFRunLoopRunSpecific PurpleEventCallback _UIAplicationHandleEvent sendEvent: handleEvent:withNewEvent:
After this trace there are two separate traces. What causes this and how can I fix it?
edit:
The leak is on the second line according to instruments
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil); //leak
[pool release];
return retVal;
Are you missing a NSAutoReleasePool for the threads?
That second method looks like some sort of callback being invoked by another component or system thread.
In the implementation, create a NSAutoReleasePool at the top and release it when the method is done:
void MyCallback {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// do stuff
[pool release];
}
It might be a false positive. UIApplicationMain probably creates a few objects that are intended to hang around for as long as the application exists and therefore never bothers to release them.