Re: Why is this code leaking memory?
Re: Why is this code leaking memory?
- Subject: Re: Why is this code leaking memory?
- From: Simon Stapleton <email@hidden>
- Date: Sat, 21 Dec 2002 10:53:14 +0100
From: matt neuburg <email@hidden>
Subject: Re: Why is this code leaking memory?
To: Jan Van Boghout <email@hidden>
cc: email@hidden
On Thu, 19 Dec 2002 20:31:26 +0100, Jan Van Boghout
<email@hidden> said:
I have two lines that load an imageRep of an image on the HD, and
they're leaking memory like hell. Any ideas why this is happening? It
shouldn't, that's the problem.
Code:
imageRep = [NSBitmapImageRep imageRepWithData:[NSData
dataWithContentsOfFile:@"/Library/Desktop Pictures/Aqua Blue.jpg"]];
[imageRep release];
Say I want to load the Aqua Blue desktop pic. *Every* time this gets
called my test app's virtual memory usage increases with 3 MB or more
(1) Reading virtual memory usage from some high-level tool such as
"top", "ps" or Process Viewer tells you nothing about whether you are
leaking. The issue is complex, and has been well explained by various
people, especially Bill Bumgarner, so please, search the archives. At
bottom level you must not expect memory usage to shrink each time you
do a release, because malloc/free doesn't work that way; freed memory
can simply be kept on hand in case it is needed again. And the virtual
memory system sits on top of this and makes things even more
complicated. The only way to know if you are leaking memory is to look
at what objects you've got. If the number of them doesn't go up
between invocations, you're not leaking.
(2) Your code may leave objects lying around merely because it uses
some autorelease objects. To get rid of autoreleased objects promptly,
wrap the call in an NSAutoreleasePool alloc/init and release.
(3) I'm less confident about the relevance of this point, but I seem
to recall that to get rid of the cached version of an NSImage, one
must recache it. Maybe there's some similar device needed here (sorry
I dont know what it is). m.
I've been meaning to reply to this thread for a while, but have been a
bit tied up, so...
First off, as Matt says above, trying to spot leaks via top, ps,
processviewer etc is a painful, error-fraught, and usually futile
exercise.
You have tools in your developer directory which will do this for you
in a much nicer way, however. If you're in ObjC, which I assume you
are, use ObjectAlloc. This is the one tool that sold a TiBook to a
previously PC using developer friend of mine. Seriously. I've never
come across anything as nice. In your case, what you want to do is
fire up your app through OA, set it to 'show since mark', wait till
it's stabilised, hit the 'mark' button, then do whatever UI action is
necessary to cause your suspected leak, then exit the app. You'll have
a nice bar graph of leaked objects, with call stacks and everything.
However, in this case, your code does not appear to leak.
Here's what I knocked together in 20 seconds to check it, based on what
you posted.
#import <Cocoa/Cocoa.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
id imageRep = [NSBitmapImageRep imageRepWith
Data:[NSData
dataWithContentsOfFile:@"/Library/Desktop Pictures/Aqua Blue.jpg"]];
NSLog (@"RC is %d", [imageRep retainCount]);
[pool release];
return 0;
}
As expected, the NSLog outputs "RC is 1".
If you run this through the debugger, and put a break on [NSImageRep
dealloc], you can even watch your image rep being deallocated, as
expected, in the [pool release] line.
There may be something you're doing elsewhere that's hanging onto the
imagerep - you don't say what you're actually doing with it after
creation - but the code you posted simply does not leak as far as I can
see (although, as originally posted, it does SEGV ;-). If it does leak
in your codebase, it's probably due to something you're doing to the
imageRep later (retaining it somewhere and forgetting to release it,
that sort of thing)
All this, of course, is not to say that your code doesn't leak. It may
even be tickling a subtle bug in AppKit, although I doubt it. If you
want someone else to take a look at it, feel free to mail me the code
offlist and I'll see what I can do.
And as a followup to your last post..
From: Jan Van Boghout <email@hidden>
Apparently my data and something else is leaking (probably the
imageRep). But that still doesn't solve the problem Why would the code
leak?
Process 672: 7725 nodes malloced
Process 672: 2 leaks
Leak: 0x001aa2a0 size=190
0x00000000 0x00000000 0x00000000 0x6d6f7573
0x00000005 0x00000001 0x40c6d6e1 0x6976bc1f
0x00000001 0x00000001 0x00000000 0x00000000
0x01626c65 0x00010002 0x00000070 0x00000005
0x43f68000 0x440ec000 0xc44b0000 0xc4200000
0x00000aa2 0xaa78eb58 0x00000100 0x0000004b
0x0000ee1f 0x000006f4 0x00000001 0x00000000
0x0000ffff 0x00000000 0x00000000 0x00000000
...
Leak: 0x00086220 size=30 instance of 'NSCFData'
0x0004ebb0 0x00010584 0x00000145 0x00000200
0x00000000 0x000863c0 0xa1b1c1d3
Given that you were complaining about a 3MB leak on every image load,
I'd suggest that these (220 bytes total) are not the leaks you're
looking for. However, you could try using the MallocStackLogging
environment variable (see `man leaaks`) and find out where these leaks
are actually coming from. Or use ObjectAlloc as I suggested above,
which is much nicer to use.
And then, as a final comment: You say in your original post that you
don't have to deal with loading multiple images; may I ask why you're
loading the image multiple times rather than doing it once and keeping
it around as long as you need it?
Hope this is of some help.
Simon
--
AppleCare. Now _there's_ an oxymoron for you.
--
PGP Key Id : 0x50D0698D
--
PGP Key Id : 0x50D0698D
--
Well, we finally have an indoor toilet. But what new disasters have
struck the Alpenproject?
Find out at : <
http://www.tufty.co.uk/Move/index.html>
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.