2012-10-16 99 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