2012-10-16 2 views
0

OSX에서 이미지를로드하기 위해 C++ 응용 프로그램에서 objective C를 사용하고 있습니다. 그것은 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; 
} 

덕분에이 함수를 호출 할 때마다 메모리 누수가 발견되었습니다. Instruments는 [NSImage TIFFRepresentation][NSBitmapImageRep bitmapData]이 엄청난 양의 메모리를 사용한다고 말합니다.

컨트롤에서 벗어나지는 않지만이 함수를 호출 할 때마다 메모리 사용량이 몇백 킬로바이트 올라갑니다.

objective-c에 대한 나의 경험이 제한되어 있으므로 release이 잘 작동한다고 생각하여이를 수정하는 방법을 모르겠습니다.

OpenGL 텍스처가 나중에 해제되고 메모리 누수의 원인이 아닌 것을 확인했습니다.

편집 : 몇 가지 추가 테스트를 한 후에 이론적으로 메모리 누수가 아니라는 것을 발견했습니다. Instruments는 "메모리 누수"를보고하지 않으므로 이론적으로 메모리 누수가 아닙니다. 그러나이 함수가 호출 될 때마다 응용 프로그램의 메모리 사용량은 계속 올라갑니다. 이 함수는 게임의 장면이로드 될 때 호출되므로 장면이로드 될 때마다 메모리 사용량이 몇 메가 바이트 증가합니다. 어떻게 이런 일이 일어날 수 있겠습니까? 나는이 함수가 모든 메모리를 다 사용하고 있다고 확신한다.

답변

1

첫 번째 꺼짐 : 코드가 새는 것처럼 보이지 않습니다. 내 생각 엔 NSImage가 무해한 캐싱을 내부적으로 수행하고 있기 때문에이 이미지 파일을 두 번로드하면 동일한 NSImage를 다시 사용할 수 있습니다. 이는 아마도보고있는 것일 수 있습니다. 아니면 파일 시스템 캐시 일 수도 있습니다. 메모리가 부족하면 이러한 캐시가 플러시되고 해제 된 메모리가 응용 프로그램에서 사용할 수있게됩니다.

즉, 코드가 지나치게 복잡해 보입니다. NSImage (NSImageReps로 구성되어 있는데 그 중 하나가 NSBitmapImageRep 일 가능성이 높음)를 만든 다음 TIFFRepresentation을 얻습니다. 즉, TIFFRepresentation을 가져옵니다 (다시 말하면 TIFF로 다시 인코딩하고 다시 압축 할 수도 있음). 그런 다음 NSBitmapImageRep을 만듭니다 (압축 해제 및 디코딩 TIFF 다시), 그리고 나서 그것의 bitmapData를 얻는다.

적어도 파일에서 NSData를 작성하고 NSBitmapImageRep을 작성해야합니다. 그러면 전체 NSImage 작성 및 TIFF 단계를 건너 뜁니다.

더 낮은 레벨의 ImageIO 라이브러리를 사용하고 방금 사용했다면 더 좋을 것입니다. 파일에서 CGImageRef를 만든 다음 이미지의 원시 압축 해제 된 데이터를 OpenGL에 넘깁니다. 내가 CIImage 또는 CoreVideo를 통해 간다면 OpenGL 텍스처를 만드는 더 좋은 방법이있을 수도 있다는 것을 모호하게 기억하지만, 역으로 (텍스처를 CIImage로) 혼합 할 수도 있습니다.

+0

조언을 주셔서 감사합니다. 이제 SOIL 이미지 라이브러리를 사용합니다. – Constan7ine