Noob: Cant Find a Memory Leak in Texture Engine
I have adapted the following code from gamewiki and some other source.
I am trying to call this method to load up sequences of very large tiles to show an action. Then destroy the texture and free the memory before calling up the next action.
Based on code performance and the MallocDebug I am pretty sure there is a memory leak here but I can't figure it out. Any Ideas?
I am trying to call this method to load up sequences of very large tiles to show an action. Then destroy the texture and free the memory before calling up the next action.
Based on code performance and the MallocDebug I am pretty sure there is a memory leak here but I can't figure it out. Any Ideas?
Code:
- (void)textureEngine: (GLboolean)firstMethodCall:(NSString *)imagename:(int)i:(int)angle{
CGImageRef image;
CGImageSourceRef theSource;
CGDataProviderRef provider;
CFStringRef path;
CFURLRef url;
size_t myCount=IMAGE_COUNT+1;
NSString *filename;
if(!firstMethodCall){free(image_base);}
image_base = (GLubyte *) calloc(myCount ,image_size * image_size * (IMAGE_DEPTH >> 3));
filename = [[[NSBundle mainBundle] pathForResource:imagename ofType:@"png"] cString];
path = CFStringCreateWithCString (NULL, filename,kCFStringEncodingUTF8);
url = CFURLCreateWithFileSystemPath (NULL, path,kCFURLPOSIXPathStyle, NULL);
CFRelease(path);
provider = CGDataProviderCreateWithURL (url);
CFRelease (url);
theSource = CGImageSourceCreateWithDataProvider(provider, NULL);
image = CGImageSourceCreateImageAtIndex(theSource,0,NULL);
width = CGImageGetWidth(image);
height = CGImageGetHeight(image);
data[i] = image_base + i * (width * height * 4);
GLint dt = i+1; //signedness issue??
CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(data[i], width, height, 8,width * (IMAGE_DEPTH >> 3), color_space, kCGImageAlphaPremultipliedFirst);
CGContextDrawImage(context,CGRectMake(0, 0, width, height),image);
[[self openGLContext] makeCurrentContext];
[[self openGLContext] update];
if(!firstMethodCall){glDeleteTextures(1, &dt);}
glDisable(GL_TEXTURE_2D);
glEnable(GL_TEXTURE_RECTANGLE_EXT);
glBindTexture(GL_TEXTURE_RECTANGLE_EXT, dt);
if(texture_range) glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_EXT, (IMAGE_COUNT+1) * width * height * (IMAGE_DEPTH >> 3), image_base);
else glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_EXT, 0, NULL);
glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_STORAGE_HINT_APPLE , texture_hint);
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, client_storage);
glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA, width,height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data[i]);
CFRelease(context);
CFRelease(color_space);
CFRelease(image);
CFRelease(theSource);
CGDataProviderRelease (provider);
}
Where does leaks say your leaks are?
Does OpenGL profiler say you have an ever-increasing number of texture objects?
Does OpenGL profiler say you have an ever-increasing number of texture objects?
Thanks for the reply.
I should state that after I diagnosed the problem I saw your post of a few days ago and switched
to
which seems to have helped, although I did not realize it because the performance still drags. As of right now MallocDebug is telling me that there is a leak at MDCalloc, but this does not appear to be growing with calls to the texture engine. From what I can tell OpenGL profiler is showing 13 textures in the resources window after every call so I think that is a good sign too.
I have a suspicion the problem is the speech recognizer I implemented elsewhere.
Thanks for the tips.
UDPDATE:
No, not the speech recognition... Now MallocDebug is finding the leak grows from a source called "start" under NSApplicationMain. I trace this down to MDCalloc in the standard view.
hmmm...
Well it doesn't appear to be an OpenGL thing at any rate.
I should state that after I diagnosed the problem I saw your post of a few days ago and switched
Code:
image_base = (GLubyte *) malloc (myCount * image_size * image_size * (IMAGE_DEPTH >> 3));to
Code:
image_base = (GLubyte *) calloc(myCount ,image_size * image_size * (IMAGE_DEPTH >> 3));which seems to have helped, although I did not realize it because the performance still drags. As of right now MallocDebug is telling me that there is a leak at MDCalloc, but this does not appear to be growing with calls to the texture engine. From what I can tell OpenGL profiler is showing 13 textures in the resources window after every call so I think that is a good sign too.
I have a suspicion the problem is the speech recognizer I implemented elsewhere.
Thanks for the tips.
UDPDATE:
No, not the speech recognition... Now MallocDebug is finding the leak grows from a source called "start" under NSApplicationMain. I trace this down to MDCalloc in the standard view.
hmmm...
Well it doesn't appear to be an OpenGL thing at any rate.
You never free(image_base), that's your leak.
Calling calloc rather than malloc won't've changed anything except the behavior when loading transparent images.
Calling calloc rather than malloc won't've changed anything except the behavior when loading transparent images.
OneSadCookie Wrote:You never free(image_base), that's your leak.
Here is where I thought I free image_base after the first method call.
Code:
if(!firstMethodCall){free(image_base)};the idea being that every subsequent call will free before allocating it again.
On the other hand
When I simply append the method with...
Code:
free(image_base);at the end, I get an exception.
that's because you free the image_base before you ever allocate memory for it. Just return if firstMethodCall is NULL, and free the image_base in the last line of your function. (at the VERY last line of your function), free(image_base).
in plain code:
in plain code:
Code:
- (void)textureEngine: (GLboolean)firstMethodCall:(NSString *)imagename:(int)i:(int)angle{
CGImageRef image;
CGImageSourceRef theSource;
CGDataProviderRef provider;
CFStringRef path;
CFURLRef url;
size_t myCount=IMAGE_COUNT+1;
NSString *filename;
if(!firstMethodCall){return;} // if firstMethodCall is NULL, get out of the function.
//You might want to a) return an error value, or b) check whether image_base is NULL and error on that.
image_base = (GLubyte *) calloc(myCount ,image_size * image_size * (IMAGE_DEPTH >> 3));
filename = [[[NSBundle mainBundle] pathForResource:imagename ofType:@"png"] cString];
path = CFStringCreateWithCString (NULL, filename,kCFStringEncodingUTF8);
url = CFURLCreateWithFileSystemPath (NULL, path,kCFURLPOSIXPathStyle, NULL);
CFRelease(path);
provider = CGDataProviderCreateWithURL (url);
CFRelease (url);
theSource = CGImageSourceCreateWithDataProvider(provider, NULL);
image = CGImageSourceCreateImageAtIndex(theSource,0,NULL);
width = CGImageGetWidth(image);
height = CGImageGetHeight(image);
data[i] = image_base + i * (width * height * 4);
GLint dt = i+1; //signedness issue??
CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(data[i], width, height, 8,width * (IMAGE_DEPTH >> 3), color_space, kCGImageAlphaPremultipliedFirst);
CGContextDrawImage(context,CGRectMake(0, 0, width, height),image);
[[self openGLContext] makeCurrentContext];
[[self openGLContext] update];
if(!firstMethodCall){glDeleteTextures(1, &dt);}
glDisable(GL_TEXTURE_2D);
glEnable(GL_TEXTURE_RECTANGLE_EXT);
glBindTexture(GL_TEXTURE_RECTANGLE_EXT, dt);
if(texture_range) glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_EXT, (IMAGE_COUNT+1) * width * height * (IMAGE_DEPTH >> 3), image_base);
else glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_EXT, 0, NULL);
glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_STORAGE_HINT_APPLE , texture_hint);
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, client_storage);
glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA, width,height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data[i]);
CFRelease(context);
CFRelease(color_space);
CFRelease(image);
CFRelease(theSource);
CGDataProviderRelease (provider);
free(image_base); // Free the allocated memory here.
}It's not magic, it's Ruby.
Nayr Wrote:that's because you free the image_base before you ever allocate memory for it. Just return if firstMethodCall is NULL, and free the image_base in the last line of your function. (at the VERY last line of your function), free(image_base).
I was not clear. When I free at the last line I eliminate the firstMethodCall switch from my code. So no I am not freeing before I allocate.
I do think I solved the problem however:
I should have freed data[i] and image_base so now I use:
Code:
if(!firstMethodCall){
free(image_base);
free(data[i]);
}I have to run the tools but the performance is 100% better.
I am still puzzled why I am getting the error when I free image_base conventionally at the very last line. I wonder if it has to do with the fact that glTextureRangeAPPLE is holdling onto a pointer to image_base???
Thanks for everyone's input, anyway
Yeah, you're using client storage which means you gotta keep the image data around. Sorry.
OneSadCookie Wrote:Yeah, you're using client storage which means you gotta keep the image data around. Sorry.
No Apologies necessary. I always learn something from your replies. Thanks again
Possibly Related Threads...
| Thread: | Author | Replies: | Views: | Last Post | |
| Can someone help a 'noob'? What's wrong with this? | RagingAvatar | 7 | 3,725 |
Jun 4, 2006 11:54 PM Last Post: Fenris |
|
| Dreaded noob questions: OpenGL in a Cocoa App | 5thPeriodProductions | 5 | 4,050 |
Apr 10, 2006 11:08 AM Last Post: 5thPeriodProductions |
|
| Small nooB question. | hyperzoanoid | 3 | 2,527 |
Apr 25, 2003 10:23 AM Last Post: DoG |
|

