2010-07-28 2 views
0

Я создаю очень большой буфер (называемый Буфер2 в коде), используя CGDataProviderRef со следующим кодом:CGDataProvider не освобождает данные на обратный вызов

-(UIImage *) glToUIImage { 
NSInteger myDataLength = 768 * 1024 * 4; 
// allocate array and read pixels into it. 
GLubyte *buffer = (GLubyte *) malloc(myDataLength); 
glReadPixels(0, 0, 768, 1024, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 

// gl renders "upside down" so swap top to bottom into new array. 
// there's gotta be a better way, but this works. 
GLubyte *buffer2 = (GLubyte *) malloc(myDataLength); 
for(int y = 0; y <1024; y++) 
{ 
     for(int x = 0; x <768 * 4; x++) 
     { 
       buffer2[(1023 - y) * 768 * 4 + x] = buffer[y * 4 * 768 + x]; 
     } 
} 

// make data provider with data. 
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer2, myDataLength, &releaseBufferData); 

// prep the ingredients 
int bitsPerComponent = 8; 
int bitsPerPixel = 32; 
int bytesPerRow = 4 * 768; 
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); 
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault; 
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault; 

// make the cgimage 
CGImageRef imageRef = CGImageCreate(768, 1024, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent); 

// then make the uiimage from that 
UIImage *myImage = [UIImage imageWithCGImage:imageRef]; 

free(buffer); 
//[provider autorelease]; 
CGDataProviderRelease(provider); 
CGColorSpaceRelease(colorSpaceRef); 
CGImageRelease(imageRef); 

return myImage; 

}

я ожидаю CGProvider позвонить верните метод releaseBufferData, когда это делается с буфером 2, чтобы я мог освободить память, которую он сделал. Код этого метода:

static void releaseBufferData (void *info, const void *data, size_t size){ 
free(data); 
} 

Однако, даже если мой метод обратного вызова вызывается, память, что данные (Буфер2) принимает никогда не освобождается, и, следовательно, это приводит к массовым утечкам памяти. Что я делаю не так?

ответ

-1

По какой-то своеобразной причине это уже не проблема.

+0

Проблемы, которые загадочно фиксируют себя, являются подклассом проблем, которые вы не можете исправить ... о, хорошо, рад, что это сработало для вас (если бы это работало для меня). – PeterT

+0

Это потому, что, к счастью, так получилось, что malloc и ваш обратный вызов «release» вызывается в том же потоке. Проблема может повториться.Если это так, пропустите обратный вызов и вместо этого используйте «free», а также тот же поток, что и malloc. –

1

У вас когда-либо было CGDataProviderReleaseprovider? Обратный вызов не будет вызываться, если вы не освободите поставщика данных.

+0

Да, действительно. Я отредактировал этот вопрос, чтобы включить полный метод. Большое спасибо. – ar106

-1

На всякий случай это помогает кому-то еще. У меня была такая же проблема. Он начал работать, когда я назвал

CGImageRelease(imageRef); 

прямо перед

CGDataProviderRelease(provider); 
+0

Это может быть правильный порядок; но, я уверен, это не связано или проблема. –

-1

malloc не освобожденные в «освобождении» обратный вызов, когда он выделяет в одном потоке, но обратном вызове, который освобождает ее выполнение на другом , Оберните как свое распределение, так и освобождение в этом:

dispatch_async(dispatch_get_main_queue(), ^{ 
// *malloc* and *free* go here; don't call &releaseCallBack or some such anywhere 
}); 

Вторая вещь, которую нужно попробовать - это блок завершения. Вместо возврата изображения традиционным способом (с помощью свойства return метода) используйте блок завершения. UIImage будет освобожден, как только блок завершения будет закрыт.

Например, если вы пытаетесь сохранить несколько изображений в библиотеке фотографий, но данные malloc'd не освобождаются после создания каждого изображения, а затем передайте изображение через блок завершения, убедившись, что вы не создают новый экземпляр образа, который передается обратно, и он уже не будет, как только он попадает в };

Третья вещь calloc вместо таНос:

GLubyte * буфер = (GLubyte *) calloc (myDataLength, sizeof (GLubyte));

Это то, что я использую сейчас, когда у меня когда-то был malloc, который устраняет необходимость в двух предыдущих предложениях. Я использую OpenGL для заполнения представления коллекции, состоящего из одной строки ячеек, каждая из которых имеет один кадр из видео. Чтобы отключить просмотр видео, вы перемещаете представление коллекции, если вы видите кадр, который хотите сохранить как изображение, вы долго нажимаете его; если вы хотите перейти к этому кадру в видео, вы нажимаете его. Как вы знаете, даже короткие видеоролики имеют много кадров; решение calloc сбивает около 256 МБ от общего использования памяти каждый вызов обратного вызова релиза, к которому он строит, когда вы прокручиваете размытие быстро.

+0

Это неправильно. 'malloc()' и 'free()' работают отлично по потокам. –

+0

Вы на самом деле попробовали мой ответ или пересканули то, что я сказал, а затем позвонили мне неправильно? –

+0

Я этого не писал; и я снова вас спрашиваю: вы попробовали решение или нет? –

Смежные вопросы