I am using this line of code in iphone 2.0 its work fine
pool=[[NSAutoreleasePool alloc]init];
[pool release];
When i run this line of code in iphone 3.0 its give some leak message in the log screen..
That message is
2009-10-13 03:26:31.841 Spectrum[3946:4c2b] *** _NSAutoreleaseNoPool(): Object 0xd819d0 of class NSCFString autoreleased with no pool in place - just leaking
Stack: (0x305a2e6f 0x30504682 0x52c14d 0x536f67 0x3058deff 0xb049 0xa554 0x3050a79d 0x3050a338 0x97181155 0x97181012)
can anyone help me?
Thanks in advance....
Your pool allocation and release code looks fine. The error message, nevertheless, indicates something was allocated with autorelease outside the scope of an autorelease pool. This often happens in when you use a secondary thread, when using some specialty load methods, and when initializing globals.
Once you isolate the leaking bit of code, you could try wrapping it by another set of NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; and [pool release];.
That message occurs when an object is sent the autorelease message outside of an autorelease scope. Place a breakpoint on _NSAutoreleaseNoPool and check the stack to see where the pool needs to be added.
Look for any place in your code where you make autoreleased objects, while inside another thread than your main run loop.
Related
i got an message at my log file (GDB) as object is leaking...
NsAutorelease pool.. like something nearly for 10 times.
Can anyone explain me. why this message is displaying..?
Thanks in advance.
It means you are autoreleasing objects with no autorelease pool in place. So those objects are not being released, and are probably leaking as a result.
So you should make sure you have a pool in place.
I generally use:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Your autoreleased objects
[pool release];
But it depends on where in your code you're running in to the issue... Are you using multi-threading? Or is everything happening in the main thread?
I have called a method in separate thread in viewdidload method
[NSThread detachNewThreadSelector:#selector(callWebService) toTarget:self withObject:nil];
-(void)callWebService{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[NSThread detachNewThreadSelector:#selector(loadImages) toTarget:self withObject:nil];
[pool release];
}
-(void)loadImages{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[self performSelectorOnMainThread:#selector(reloadTable) withObject:nil waitUntilDone:false];
[pool release];
}
-(void)reloadTable
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[myTableView reloadData];
[pool release];
}
How to handle leaks while using thread? I want to use threads.
Errors
*** __NSAutoreleaseNoPool(): Object 0x604b830 of class NSCFString autoreleased with no pool in place - just leaking
*** -[NSAutoreleasePool release]: This pool has already been drained, do not release it (double release).
The autorelease pool must be drain, not release. So I think if you change it to [pool drain] it should be working fine.
Don't know if you found your answer yet, but as I had hit something similar to your problem, I did some looking. It seems that when you drain a pool, that is (effectively) equivalent to releasing it. The documentation on the class says:
Since you cannot retain an autorelease pool (or autorelease it—see
retain and autorelease), draining a pool ultimately has the effect of
deallocating it.
So, you should only drain a pool once. If you need another context after that point, you should generate a new pool in the same way you generated one earlier in your code.
If there is no pool available, then you can end up leaking (as you mentioned). However, autorelease calls should log a warning message in that instance. Regarding threads, the documentation has this to say
The Application Kit creates an autorelease pool on the main thread at
the beginning of every cycle of the event loop, and drains it at the
end, thereby releasing any autoreleased objects generated while
processing an event. If you use the Application Kit, you therefore
typically don’t have to create your own pools. If your application
creates a lot of temporary autoreleased objects within the event loop,
however, it may be beneficial to create “local” autorelease pools to
help to minimize the peak memory footprint.
Hope this helps.
I haven't noticed my console output for a while and I've suddenly noticed lots of weird errors.
__NSAutoreleaseNoPool(): Object 0x753c2f0 of class General autoreleased with no pool in place - just leaking
__NSAutoreleaseNoPool(): Object 0x753c300 of class __NSArrayM autoreleased with no pool in place - just leaking
I've no idea where this happening?
Edit..
I use this
[self performSelectorInBackground:#selector(startupStuff) withObject:sender];
With statupStuff I have this
General *rdb = [[General alloc] autorelease];
[rdb refreshDBData];
The Errors happen shortly after code in the refreshDBData method.
Autorelease pools are tied to threads. If you create a thread through performSelectorInBackground then you need to create and destroy an autorelease pool for yourself. So you need startupStuff to look like this:
- (void)startupStuff:(id)sender
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// ... everything else you were doing ...
[pool drain]; //see comment below
}
Addition: Richard below makes the point that drain is preferable to release to acknowledge that (on the desktop, not yet on iOS) you may be running with a garbage collector. Apple's specific words are (source):
In a garbage-collected environment, sending a drain message to a pool triggers garbage collection if necessary; release, however, is a no-op. In a reference-counted environment, drain has the same effect as release. Typically, therefore, you should use drain instead of release.
So I've corrected my example. Suffice to say, this specific question is to do with the iPhone and currently there is no garbage collection on that device. So the originating poster is in the "drain has the same effect as release" camp, not the "drain ... triggers garbage collection if necessary; release, however, is a no-op" camp.
This:
General *rdb = [[General alloc] autorelease];
Is wrong. There should always be a call to an initializer; to -init, at the least.
Try this
[self performSelectorInBackground:#selector(startupStuff) withObject:sender];
-(void)startupStuff:(id)sender
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
General *rdb = [[General alloc] init];
[rdb refreshDBData];
[rdb release];
[pool release];
}
If its not working too then you need to check refreshDBData method.. you are doing something wrong there
Does anyone know what this error means?
*** attempt to pop an unknown autorelease pool
I am seeing this in my app that uses NSOperations in NSOperationQueue. Each operation has it's own Autorelease pool. Since each operation is parsing xml and pushing information into Core Data, I periodically 'drain' my autorelease pool and re-create it. If I don't drain the pool, I don't see these errors.
UPDATE:
Here's my code:
In the main of my NSOperation, I alloc the pool and assign it to an 'assign' property like this:
self.downloadAndParsePool = [[NSAutoreleasePool alloc] init];
at the end of my main I release it like this:
[self.downloadAndParsePool release];
self.downloadAndParsePool = nil;
If the operation does a lot of parsing and inserting into Core Data, it will call my drain method periodically:
- (void) drainAutoreleasePool
{
// drain and re-create autorelease pool...this method is called periodically to keep memory down during parsing of large trees
if (self.downloadAndParsePool)
{
[self.downloadAndParsePool drain];
self.downloadAndParsePool = [[NSAutoreleasePool alloc] init];
}
}
It seems that the issue is caused by the fact that the drain is called outside of the method that allocated the pool even if on the same thread. Here is what NSAutoreleasePool Class Reference says.
You should always drain an autorelease
pool in the same context (invocation
of a method or function, or body of a
loop) that it was created.
The message you see is triggered by your call to drain in drainAutoreleasePool:
[self.downloadAndParsePool drain];
NOTE: XMLPerformance sample app uses the same pattern of periodically draining the pool. It also produces this message since iOS4.0
How To Actually Fix This
The accepted answer here is correct, but here are some more details on how to fix it because it's not a good idea to just live with issues that are filling up your console. A log statement is being printed and there is a reason for it. Something is awry.
Turns out this code is from Apple's own example project called XMLPerformance, found here: http://developer.apple.com/library/ios/#samplecode/XMLPerformance/Introduction/Intro.html
In the source file, LibXMLParser.m, simply change this line:
self.downloadAndParsePool = [[NSAutoreleasePool alloc] init];
to this:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
at the beginning of the - (void)downloadAndParse:(NSURL *)url method and then change:
[downloadAndParsePool release];
self.downloadAndParsePool = nil;
to this:
[pool release], pool = nil;
at the end of that method. Now remove the ivar called downloadAndParsePool. Once you've done all of that, the messages will go away.
Magically delicious.
It sounds like you've lost a pool somewhere. Pools are objects and its possible for them to be over released. They also stack in a fashion. IIRC, when you have nested pools, draining an outer pool automatically drains the inner pools. I think you've got a pool object that dies without being drained. When the outer pool tries to drain it, it never gets a response.
Just a guess.
It would be very helpful if you could show the code that does the creation of the pool, the drain of the pool and the re-creation of it. Otherwise we are just guessing at answers.
update
First, pools like that should be a local variable inside of the -main instead of an iVar like that. Second, how is your property defined? Is it an assign or a retain?
Update2
I would still recommend against using an iVar to store that pool. Nevertheless since it is an assign that should be fine.
When you drain the pool, are you also saving and resetting the NSManagedObjectContext associated with that operation? NSManagedObjectContext makes very heavy use of the autorelease pool and if you are not resetting it at the same time as the drain that could be causing an error.
Update3
Ok, then we are left with TechZen's suggestion that you are losing a pool somewhere. I would put log statements in after you create a pool and spit out its pointer address and put a log statement in just before the drain that also spits out the pointer address. Then match them up. If they match up then the leak is somewhere else.
If you create a pool with NSAutoReleasePool
So that it automatically releases
there is no need for release in dealloc
The app sometimes crashes if you use NSAutoReleasePool
and also release the pool in dealloc
I do this:
NSString *fullpath = [[NSBundle mainBundle] pathForResource:#"text_file" ofType:#"txt"];
Why the following message appear?
Is my code leaking?
2010-03-31 13:44:18.649 MJIPhone[2175:207] *** _NSAutoreleaseNoPool(): Object 0x3909ba0 of class NSPathStore2 autoreleased with no pool in place - just leaking
Stack: (0x1656bf 0xc80d0 0xcf2ad 0xcee0e 0xd3327 0x2482 0x2426)
2010-03-31 13:44:18.653 MJIPhone[2175:207] *** _NSAutoreleaseNoPool(): Object 0x390b0b0 of class NSPathStore2 autoreleased with no pool in place - just leaking
Stack: (0x1656bf 0xc80d0 0xc7159 0xd0c6f 0xd3421 0x2482 0x2426)
2010-03-31 13:44:18.672 MJIPhone[2175:207] *** _NSAutoreleaseNoPool(): Object 0x390d140 of class NSCFString autoreleased with no pool in place - just leaking
Stack: (0x1656bf 0xc6e62 0xcec1b 0xd4386 0x24ac 0x2426)
This happens because you are running in a thread. User threads don't share the main threads autorelease pool, so you need to create your own. Otherwise, objects like these will never get released, thus leaking.
In the beginning of your thread method, before the loop or whatever, do:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Before returning, release it:
[pool drain];
At the time you run that line of code, no NSAutoreleasePool has been created on the current thread.
If you're running on the main thread, Cocoa (and Cocoa Touch) automatically provides an autorelease pool for you. If you've scheduled something to happen on a separate thread (which would also include something scheduled by performSelectorInBackground:withObject:), then you need to provide your own autorelease pool.