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.
Related
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 thread2 loop where i do assembly (create from raw bytes data) some UIImage
in every iteration of this loop
thread2loop()
{
//make UIIamge here
[self performSelectorOnMainThread:#selector(setUiImage) withObject:nil waitUntilDone:YES];
}
there and then i call setUIImage method on the main thread
- (void) setUiImage
{
self.imageView.image = nil;
self.imageView.image = mImage;
[mImage release];
}
it is working but the Instruments , leaks application shows to me that there are
UIImage leaks here and i do not know how to ##$! get rid of it! (im sad and little tired
and bored), help, what to do, tnx
Surround your threaded code with...
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
//threaded code....
[pool release];
Classic producer/consumer problem. Your producer thread is probably outrunning the main thread (the consumer). I'd recommend keeping a queue of images (instead of the single mImage), guarded by a lock which you enqueue images onto (from your background queue), and dequeue images from your main queue. Or you could use GCD, which makes this even easier. Instead of using mImage to hold onto the created image, you could just use a block which would retain the image and then set it on your image view in the main queue. Something like:
thread2loop() {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
while (...) {
__block id self_block = self; // (don't want to retain self in the block)
UIImage *img = [[UIImage alloc] initWithCGImage:quartzImage scale:1.0 orientation:UIImageOrientationUp];
dispatch_async(dispatch_get_main_queue(), ^{
block_self.imageView.image = img;
[img release];
});
}
[pool drain]; // release is outdated for autorelease pools
}
Warning: Doing this too much will quickly run the device out of memory and cause your app to be killed. You probably want to make sure that your use of this technique is limited to creating a small number of images.
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 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;
}
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.