Welcome to the MacNN Forums.

If this is your first visit, be sure to check out the FAQ by clicking the link above. You may have to register before you can post: click the register link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below.

You are here: MacNN Forums > Software - Troubleshooting and Discussion > Developer Center > Weird Memory leak

Weird Memory leak
Thread Tools
Professional Poster
Join Date: Dec 2000
Location: Chicago, Illinois
Status: Offline
Reply With Quote
Sep 8, 2001, 08:46 PM
 
Yeah, so this question isn't a dumbass one, I swear. Here's what I want to do: draw an image in an NSView that the user picks and can choose at a later time. I have written the code in both Java and ObjC so I'm not discriminating against anyone here. Here it is:

Java
<BLOCKQUOTE><font size="1"face="Geneva, Verdana, Arial">code:</font><HR><pre><font size=1 face=courier>
<font color = brown>/* ImageTester */</font>

import com.apple.cocoa.foundation.*;
import com.apple.cocoa.application.*;

<font color = green>public</font> class ImageTester extends NSView
{

<font color = brown>//NSTimer recompositeTimer;</font>
NSColor color;

<font color = green>public</font> ImageTester(NSRect frame)
{
<font color = purple>super</font>(frame);
}

<font color = green>public</font> <font color = green>void</font> awakeFromNib()
{
<font color = brown>//recompositeTimer = new NSTimer(<font color = blue>1</font>, <font color = green>this</font>, new NSSelector(<font color = red>"updateView"</font>, new Class[]{<font color = green>this</font>.getClass()}), <font color = green>this</font>, true);</font>
<font color = brown>//NSRunLoop.currentRunLoop().addTimerForMode(recompo siteTimer, NSRunLoop.DefaultRunLoopMode);</font>
}

<font color = green>public</font> <font color = green>void</font> drawRect(NSRect frame)
{
NSColor.clearColor().set();
NSBezierPath.fillRect(<font color = green>this</font>.bounds());

<font color = green>if</font>(color!=null)
{
color.set();
NSBezierPath.fillRect(<font color = green>this</font>.bounds());
}
}

<font color = green>public</font> <font color = green>void</font> setImage(NSButton sender)
{
NSOpenPanel me = NSOpenPanel.openPanel();
<font color = green>if</font>(me.runModalForTypes(NSImage.imageFileTypes() )==NSPanel.OKButton)
color = NSColor.colorWithPatternImage(new NSImage(new NSData(new java.io.File((String)me.filenames().objectAtIndex( <font color = blue>0</font>)))));
setNeedsDisplay(true);
}

<font color = green>public</font> <font color = green>void</font> updateView(NSTimer a)
{
setNeedsDisplay(true);
}

}
</font>[/code]

ObjC
<BLOCKQUOTE><font size="1"face="Geneva, Verdana, Arial">code:</font><HR><pre><font size=1 face=courier>
<font color = brown>/*ImageTester.h */</font>
#import &lt;Cocoa/Cocoa.h&gt;

<font color = purple>@interface</font> ImageTester : NSView
{
NSColor *color;
}

- (<font color = purple>id</font>)initWithFrame NSRect)frame;
- (<font color = green>void</font>)dealloc;

- (<font color = green>void</font>)drawRect NSRect)rect;

- (<font color = purple>IBAction</font>)setImage <font color = purple>id</font>)sender;
<font color = purple>@end</font>

<font color = brown>/*ImageTester.m */</font>
#import <font color = red>"ImageTester.h"</font>

<font color = purple>@implementation</font> ImageTester

- (<font color = purple>id</font>)initWithFrame NSRect)frame
{
[<font color = purple>super</font> initWithFrame:frame];
<font color = green>return</font> <font color = purple>self</font>;
}

- (<font color = green>void</font>)dealloc
{
[color release];
[<font color = purple>super</font> dealloc];
}

- (<font color = green>void</font>)drawRect NSRect)rect
{
[[NSColor clearColor] set];
NSRectFill([<font color = purple>self</font> bounds]);
<font color = green>if</font>(color!=<font color = green>nil</font>)
{
[color set];
NSRectFill([<font color = purple>self</font> bounds]);
}
}

- (<font color = purple>IBAction</font>)setImage <font color = purple>id</font>)sender
{
NSOpenPanel *me = [NSOpenPanel openPanel];
<font color = green>if</font>([me runModalForTypes:[NSImage imageFileTypes]]==<font color = blue>1</font>)
{
[color autorelease];
color = [[NSColor colorWithPatternImage:[[NSImage alloc] initWithData:[NSData dataWithContentsOfFile:[[me filenames] objectAtIndex:<font color = blue>0</font>]]]] retain];
[<font color = purple>self</font> setNeedsDisplay:<font color = purple>YES</font>];
}
}
<font color = purple>@end</font>
</font>[/code]

Of course they're linked in IB. But that has nothing to do with my problem. Everytime I set a new image, the ram usage goes up, even if I pick a significantly smaller image than the previous. I've been able to run up my ram usage to upwards of 100MB, which is really really bad.

My theory is that this has something to do with the way Cocoa caches images, but I don't know how to flush the cache. Does anyone know why my program likes to eat ram?

Hoping this isn't a dumbass question,
F-bacher
     
Dedicated MacNNer
Join Date: Jun 2000
Location: Dundas, Ontario, Canada
Status: Offline
Reply With Quote
Sep 9, 2001, 12:54 AM
 
I don't think that I can help you directly here but I do have a few concerns looking at the code (I am an Obj-C guy so that is what I will refer to).
I think that this init method:
<BLOCKQUOTE><font size="1"face="Geneva, Verdana, Arial">code:</font><HR><pre><font size=1 face=courier>
- (<font color = purple>id</font>)initWithFrame NSRect)frame
{
[<font color = purple>super</font> initWithFrame:frame];
<font color = green>return</font> <font color = purple>self</font>;
}
</font>[/code]
Should look something more like this:
<BLOCKQUOTE><font size="1"face="Geneva, Verdana, Arial">code:</font><HR><pre><font size=1 face=courier>
- (<font color = purple>id</font>)initWithFrame NSRect)frame
{
<font color = green>return</font> [<font color = purple>super</font> initWithFrame:frame]; <font color = brown>//remember that initWithFrame returns an <font color = purple>id</font></font>
}
</font>[/code]

Although I would not be surprised if that were just a careless error when you posted the code here.

Another issue I am curious about is that the "color" object is sent the "autorelease" message right before you declare it and then send it the "retain" message. If you are handling the retain and release commands yourself I don't think that you should put in an autorelease. I think that this could cause some unusual behavior.
I would suggest replacing the autorelease message with an explicit release (don't forget to ensure that the variable is not NULL). Basically, I think that it comes down to a misinterpretation of what "autorelease" actually does.

That should solve the leak (before things weren't ever being deallocated). Also, I don't think that you need to implement "initWithFrame" at all since you don't do anything other than what the parent object does.

Hope that helps,
Jeff.
Spectral Class
"Shedding Light on Innovation"
     
Professional Poster
Join Date: Dec 2000
Location: Chicago, Illinois
Status: Offline
Reply With Quote
Sep 9, 2001, 02:36 AM
 
That's really funny, considering I coded it almost exactly the same way that Apple's example dot view app does

I'll give it a try,
F-bacher
     
Professional Poster
Join Date: Dec 2000
Location: Chicago, Illinois
Status: Offline
Reply With Quote
Sep 9, 2001, 02:44 AM
 
Originally posted by Apocalypse:
<STRONG>Another issue I am curious about is that the "color" object is sent the "autorelease" message right before you declare it and then send it the "retain" message. If you are handling the retain and release commands yourself I don't think that you should put in an autorelease. I think that this could cause some unusual behavior.
I would suggest replacing the autorelease message with an explicit release (don't forget to ensure that the variable is not NULL). Basically, I think that it comes down to a misinterpretation of what "autorelease" actually does.
</STRONG>
Okay, so know instead of sending autorelease to color, I send release. That has zero effect on the amount of ram that is used. And if it was as simple as that, I don't think my java version would be having the same probs.

And i just tried releasing my color object right after I fill the rect (because I always define my color object right before i draw my rect). Still no dice.

Back to the drawing board,
F-bacher
     
Junior Member
Join Date: Mar 2001
Status: Offline
Reply With Quote
Sep 9, 2001, 02:50 AM
 
Change

color = [[NSColor colorWithPatternImage:[[NSImage alloc] initWithData:[NSData dataWithContentsOfFile:[[me filenames] objectAtIndex:0]]]] retain];

To

color = [[NSColor colorWithPatternImage:[[[NSImage alloc] initWithData:[NSData dataWithContentsOfFile:[[me filenames] objectAtIndex:0]]] autorelease] retain];
     
Forum Regular
Join Date: Mar 2001
Status: Offline
Reply With Quote
Sep 9, 2001, 03:09 AM
 
Originally posted by Apocalypse:
<STRONG>
Although I would not be surprised if that were just a careless error when you posted the code here.

Another issue I am curious about is that the "color" object is sent the "autorelease" message right before you declare it and then send it the "retain" message. If you are handling the retain and release commands yourself I don't think that you should put in an autorelease. I think that this could cause some unusual behavior.
I would suggest replacing the autorelease message with an explicit release (don't forget to ensure that the variable is not NULL). Basically, I think that it comes down to a misinterpretation of what "autorelease" actually does.
</STRONG>
The autorelease is actually fine where it is. The difference between autorelease and release is just timing. In the end, they both add up to 1 release being sent. There are times to use one over the other, but the difference won't cause a leak.

The return self; is also ok. Either way, it is the same pointer. It is just a matter of style.

You don't need to check if the object is NULL (or nil) because it is valid to send a message to a nil object.
     
Professional Poster
Join Date: Dec 2000
Location: Chicago, Illinois
Status: Offline
Reply With Quote
Sep 9, 2001, 03:12 AM
 
Wixar, ur a genious! (although now I sound like an idiot on MaxOSX-dev, but what else is new?) So that fixes the Obj-C prob, but what's going on with Java, which is suppose to be good at garbage collection? I can't exactly send java object autorelease and retain messages.

Thanks,
F-bacher
     
Forum Regular
Join Date: Mar 2001
Status: Offline
Reply With Quote
Sep 9, 2001, 03:12 AM
 
Originally posted by Wixar:
<STRONG>Change

color = [[NSColor colorWithPatternImage:[[NSImage alloc] initWithData:[NSData dataWithContentsOfFile:[[me filenames] objectAtIndex:0]]]] retain];

To

color = [[NSColor colorWithPatternImage:[[[NSImage alloc] initWithData:[NSData dataWithContentsOfFile:[[me filenames] objectAtIndex:0]]] autorelease] retain];</STRONG>
Just to elaborate on Wixar's correct solution... It is the NSImage that is leaking, not the NSColor.
     
Professional Poster
Join Date: Dec 2000
Location: Chicago, Illinois
Status: Offline
Reply With Quote
Sep 9, 2001, 03:16 AM
 
Originally posted by unregistered:
<STRONG>

Just to elaborate on Wixar's correct solution... It is the NSImage that is leaking, not the NSColor.</STRONG>
This makes a lot of sense to me now. Cool... but got any clue about what's going on with my java version?

F-bacher
     
Addicted to MacNN
Join Date: Mar 2000
Location: London, UK
Status: Offline
Reply With Quote
Sep 9, 2001, 04:49 AM
 
Originally posted by Ghoser777:
<STRONG>This makes a lot of sense to me now. Cool... but got any clue about what's going on with my java version?</STRONG>
AFAIK, the java bridge just retains/releases the objects internally during garbage collection. If the object you have already has a retain count of 1 (or more) when it is handed across the bridge, it will never have its retain count reduced back down to 0. Can you call -release on objects that inherit from NSObject in Java? If not, you could use a really hackish workaround of creating some objc code that releases the object and then calling that across the bridge
     
Professional Poster
Join Date: Dec 2000
Location: Chicago, Illinois
Status: Offline
Reply With Quote
Sep 9, 2001, 11:24 AM
 
No, I can't just send objects "go to hell" messages like you can in Obj-C. But I can make an Obj-C clss wrapper which I pass int the fileName of the image and will do the rest as posted above, returning the color object.
http://developer.apple.com/techpubs/...aBridge.2.html

This problem shouldn't exist though.
F-bacher
     
Addicted to MacNN
Join Date: Mar 2000
Location: London, UK
Status: Offline
Reply With Quote
Sep 9, 2001, 01:58 PM
 
Originally posted by Ghoser777:
<STRONG>This problem shouldn't exist though.</STRONG>
Exactly, it's a bug. Submit a bug report http://developer.apple.com/bugreporter
     
Professional Poster
Join Date: Dec 2000
Location: Chicago, Illinois
Status: Offline
Reply With Quote
Sep 9, 2001, 03:46 PM
 
Oh, this keeps getting better and better. You know that documented java wrapper thing? It's GONE! Caput. Removed. On OS X server you use to be able to make them, but with project builders made for OS X PB and beyond, the functionality has been removed.

If I can't figure out something soon, Steve's balls are mine!
F-bacher
     
Dedicated MacNNer
Join Date: Feb 2001
Status: Offline
Reply With Quote
Sep 9, 2001, 08:24 PM
 
You can make a Java Wrapper project using ProjectBuilderWO. At WWDC the Cocoa guys said that this capability would be added to the new Project Builder, they just haven't gotten around to it yet.
     
Professional Poster
Join Date: Dec 2000
Location: Chicago, Illinois
Status: Offline
Reply With Quote
Sep 9, 2001, 10:36 PM
 
Well, i deleted ProjectBuilderWO because the new Project Builder was suppose to integrate WO support. Does anyone have a copy they could compress for me and load on a server? Or just a sample Java Wrapper project would probably do.

Thanks,
F-bacher
     
   
Thread Tools
Forum Links
Forum Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On
Top
Privacy Policy
All times are GMT -5. The time now is 02:57 PM.
All contents of these forums © 1995-2011 MacNN. All rights reserved.
Branding + Design: www.gesamtbild.com
vBulletin v.3.8.7 © 2000-2011, Jelsoft Enterprises Ltd., Content Relevant URLs by vBSEO 3.3.2