2012-10-16 75 views
0

我在C++应用程序中使用目标C在OSX上加载图像。这是一个OpenGL应用程序。这是我使用的图像加载到OpenGL的代码:NSImage和NSBitmapImageRep内存泄漏

bool OSXSpecifics::loadPNGOSX(const char *fileName, int &outWidth, int &outHeight, GLuint *outTexture) { 
NSImage *image = [[NSImage alloc] initWithContentsOfFile:[NSString stringWithUTF8String: fileName]]; 
NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithData:[image TIFFRepresentation]]; 

NSArray* imageReps = [image representations]; 

bool hasAlpha; 

for (NSImageRep *imageRep in imageReps) { 
    if ([imageRep pixelsHigh] > outHeight) { 
     outHeight = [imageRep pixelsHigh]; 
    } 
    if ([imageRep pixelsWide] > outWidth) { 
     outWidth = [imageRep pixelsWide]; 
    } 
} 
if ([bitmap hasAlpha] == YES) { 
    hasAlpha = true; 
} else { 
    hasAlpha = false; 
} 


glGenTextures(1, outTexture); 
glBindTexture(GL_TEXTURE_2D, *outTexture); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 

glTexImage2D(GL_TEXTURE_2D, 0, hasAlpha ? 4 : 3, outWidth, outHeight, 0, 
      hasAlpha ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, [bitmap bitmapData]); 
[bitmap release]; 
[image release]; 
return true; 
} 

由于仪器我已经检测到存储器泄漏每调用该函数的时间。仪器说[NSImage TIFFRepresentation][NSBitmapImageRep bitmapData]正在使用大量的内存。

它不会失去控制,但每次调用这个函数时,内存使用量都会上升几百千字节。

我对objective-c的使用经验有限,所以我不知道如何解决这个问题,因为我认为release可以正常工作。

只是让你知道OpenGL纹理在稍后的时间点被释放,并且我已经证实它不是内存泄漏的来源。

编辑:经过一些进一步的测试,我发现这不是理论上的内存泄漏,因为乐器不报告“内存泄漏”。但是,无论何时调用此函数,应用程序的内存使用量都会上升,永远不会下降。当游戏中的场景被加载时,这个函数被调用,所以每当一个场景被加载时,内存使用量就会增加几兆字节。这怎么可能发生。我确定这是使用所有内存的功能。

回答

1

首先:代码看起来不像是泄漏。我的猜测是NSImage在内部做了一些无害的缓存,以确保它可以重新使用相同的NSImage,如果你再次加载这个图像文件,那也许就是你所看到的。或者也许它是文件系统缓存。如果内存变得紧张,这些缓存可能会被刷新,释放的内存可用于您的应用程序。

也就是说,你的代码似乎过于复杂。你创建一个NSImage(它由NSImageReps组成,其中一个很可能是一个NSBitmapImageRep),然后获得它的TIFFRepresentation(即将所有数据重新编码为TIFF,可能再次压缩),然后从中创建一个NSBitmapImageRep(解压缩和解码TIFF),然后获取其bitmapData。

至少,你应该从文件中创建一个NSData并从中创建你的NSBitmapImageRep。这将跳过整个NSImage创建和TIFF步骤。

如果你只是去了,并且使用了较低级别的ImageIO库,情况会更好。从你的文件创建一个CGImageRef,然后将图像的原始解压缩数据交给OpenGL。我隐约记得,如果你通过CIImage或者CoreVideo来创建OpenGL纹理,甚至可能会有更好的方法,但是我可能会将其与反转(纹理到CIImage)混合起来。

+0

感谢您的建议,我现在使用SOIL图像库,它的工作原理 – Constan7ine