2014-02-05 4 views
4

Я пытаюсь преобразовать CVMat в UIImage, но я сталкиваюсь с утечкой памяти и не могу на всю жизнь выяснить, где. проблема кроется. Я использую ту же функцию, что openCV использует в своем примере кода Located Here.Memory Leak UIIMageFromCVMat

Код говорит следующее:

+(UIImage *)UIImageFromCVMat:(cv::Mat)cvMat{ 
    NSData *data = [NSData dataWithBytes:cvMat.data length:cvMat.elemSize()*cvMat.total()]; 
    CGColorSpaceRef colorSpace; 

    if (cvMat.elemSize() == 1) { 
     colorSpace = CGColorSpaceCreateDeviceGray(); 
    } else { 
     colorSpace = CGColorSpaceCreateDeviceRGB(); 
    } 

    CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data); 
    bool alpha = cvMat.channels() == 4; 
    CGBitmapInfo bitMapInfo = (alpha ? kCGImageAlphaLast : kCGImageAlphaNone) | kCGBitmapByteOrderDefault; 
    // Creating CGImage from cv::Mat 
    CGImageRef imageRef = CGImageCreate(cvMat.cols,         //width 
             cvMat.rows,         //height 
             8,           //bits per component 
             8 * cvMat.elemSize(),      //bits per pixel 
             cvMat.step[0],       //bytesPerRow 
             colorSpace,         //colorspace 
             bitMapInfo,         // bitmap info 
             provider,         //CGDataProviderRef 
             NULL,          //decode 
             false,          //should interpolate 
             kCGRenderingIntentDefault     //intent 
             ); 


    // Getting UIImage from CGImage 
    UIImage *finalImage = [UIImage imageWithCGImage:imageRef]; 
    CGImageRelease(imageRef); 
    CGDataProviderRelease(provider); 
    CGColorSpaceRelease(colorSpace); 

    return finalImage; 
} 

Кто-нибудь есть какие-либо предложения о том, где проблема может быть? (Мы сузились и знаем наверняка, что это место с утечкой).

Редактировать

Чтобы дать больше информации, что я нашел: Если выход функции никогда не используется, нет никаких проблем. Только если мы присвоим этому результату переменную в другом классе, в которой мы сталкиваемся с проблемами.

ответ

4

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

Все, что нужно было сделать, это обернуть строки кода, которые использовали результат этого в теге @autoreleasepool{}.

Я нашел основную идею решения от this question

+0

Я предполагаю, что вы используете НОД, как мне запустить это в фоновом потоке? Причина требования autoreleasepool приведена в документах Apple [здесь] (https://developer.apple.com/library/ios/DOCUMENTATION/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html#//apple_ref/doc/ UID/TP40008091-CH102-SW1). В принципе, GCD действительно медленно пуст пул по умолчанию. –

+2

Не помог мне, попытался поставить код в autoreleasepool, но на самом деле ничего не изменилось. – C0mrade

+0

Я пробовал autoreleasepool, но не работает. – GeneCode

0

предполагается, что вы не используете ARC, я думаю, что проблематично заявление
CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);
__bridge не передает права собственности, так CGDataProviderRelease(provider); не освобождает исходный объект.
Вы должны были либо освободить data явно или использовать __bridge_transfer для передачи права собственности на provider, который затем выпущен с CGDataProviderRelease(provider);

+0

Спасибо за ответ, но мы на самом деле используют ARC –