views:

111

answers:

4
NSString* str = [[NSString alloc] initWithString:@"0.05"];
NSDecimalNumber* num = [[NSDecimalNumber alloc] initWithString:str];
NSLog(@" %@", num);
[str release];
[num release];

leaks memory

*** __NSAutoreleaseNoPool(): Object 0x707990 of class NSCFString autoreleased with no pool in place - just leaking

Can someone suggest a workaround ?

A: 

Wrap your use of the class in an NSAutoreleasePool.

Graham Lee
This is what the OP wants to avoid.
Jacob Relkin
@Jacob: is it really? He said he wanted to work around a "__NSAutoreleaseNoPool()" leak. My answer is such a workaround (nay, solution).
Graham Lee
A: 

Internally NSDecimalNumber appears to use autoreleased NSString objects. So you need to have an autorelease pool in place to catch these.

Claus Broch
+5  A: 

What others said; wrap your code with an NSAutoreleasePool. An NSAutoreleasePool is actually surprisingly efficient; will incur very little overhead. You don't want to, say, surround every few lines of code with one, but it is unlikely that they'll be measurable in normal use.

Do not try to use Foundation without Autorelease Pools

Down that path lies madness. Don't bother. Sure -- it is sometimes a good idea to put some effort into minimizing use of pools, but there will be many cases -- like this one -- where they are unavoidable.

No, really, I'm not kidding:

Cocoa always expects there to be an autorelease pool available. If a pool is not available, autoreleased objects do not get released and you leak memory. If you send an autorelease message when a pool is not available, Cocoa logs a suitable error message.


I have C++ communication library written many years ago. It calls back every time there is network event (sometimes in a newly created thread). Your advise had disastrous effect on the performance of my application.

My answer wasn't advice, it was a very specific description of the exact rules by which the Cocoa frameworks are implemented. That your code worked before was by coincidence. While there is certainly a behavior change, it isn't a regression for code that is following the rules.

Arbitrary threading like that is exceedingly risky within Cocoa (well, really, anywhere). I've done such integrations a number of times and have generally found the best solution to be to handle the events in one or more queue like mechanisms, depending on concurrency needs. The queues can then take care of periodically dealing with autorelease pools.

Of course, the truly arbitrary threading you describe would need some mechanism to move the data over to the queue's thread(s)....

bbum
Guys I know how to use Autorelease pool. With [NSDecimalNumber initWithString:] I should be able to use my memory manually, otherwise this constructor should be removed in a favor +decimalNumberWithString: . Suggestion not to use foundation without Autorelease Pools is ridicules at least. I don't have 100 points to vote down this one.
bioffe
Try to think about it this way: Autorelease Pools is Foundations Garbage Collection for the poor, which it's relying on.
catlan
@bioffe - Trust the man, he knows what he's talking about (hint: check his place of employment). Just because your code is not immediately using autoreleased objects does not mean that none are generated behind the scenes.
Brad Larson
More than me, trust the documentation... it is quite explicit (the above is a copy/paste from the iPhone documentation).
bbum
I have C++ communication library written many years ago. It calls back every time there is network event (sometimes in a newly created thread). Your advise had disastrous effect on the performance of my application. I lost beautiful sunday evening reimplementing much of NSDecimalNumber class, but I regained back full understanding of the memory management aspect of my code. The bug is filed (it is 100% different comparing how it worked in 3.2, so it is a regression at the very least)
bioffe
I find it difficult to believe that the cost of creating an autorelease pool is significant compared to the cost of creating the thread. Have you profiled the code?
JeremyP
@JeremyP I don't create new threads. It's being done in a separate project which is statically linked to my product. I do profile my code. That is how leaks are being detected.
bioffe
bbum and big3 get kudos for their most informative answers
bioffe
@bbum FYI Apple engineering thinks its a bug. I got a confirmation email from Apple last week.
bioffe
Yes -- I know. I've been following along in the bug. :)
bbum
A: 

You haven't told us anything about the context in which this code runs. In an ordinary Cocoa or Carbon app where you're running code in response to events, autorelease pools are set up automatically.

JWWalker
It is ordinary iPhone app(Cocoa). This code works fine on 3.1.3 and 3.2. It leaks memory in iOS 4 on both simulator and device
bioffe
@bioffe in that case, file a bug with Apple
Shaggy Frog
Problem ID: 8087935
bioffe
@bioffe: I overlooked the iPhone tag on your question. But still, I hope your bug report includes a lot more information.
JWWalker
@jwwalker: Only on the main thread.
Graham Lee