2

我從磁盤讀取的圖像轉換成一個UIImage之外定義C指針對象(CGImageRef),以及在用於媒體處理另一個工作隊列塊使用其CGImage。記憶問題,使用在GCD調度隊列塊

現在我得到EXC_BAD_ACCESS如果我在主隊列定義CGImageRef,並在工作隊列使用CGImageRef。就像這樣:

UIImage *uiimage = [UIImage imageWithContentsOfFile:[aPhoto completeLargeThumbFilePath]]; 

CGImageRef cgImage = uiimage.CGImage; 

dispatch_queue_t dispatchQueue = dispatch_queue_create("mediaInputQueue", NULL); 
[writerInput requestMediaDataWhenReadyOnQueue:dispatchQueue usingBlock:^{ 

    // ... unrelated stuff 
    CVPixelBufferRef buffer = (CVPixelBufferRef)[self pixelBufferFromCGImage:cgImage size:size]; 
    // ... unrelated stuff 
}]; 

如果我直接在工作隊列使用uiimage.CGImage,那麼我不明白的例外。我認爲這與ARC內存管理有關。 UIImage是一個Objective-C對象,CGImageRef是一個指向C結構體的指針。在第一種情況下,我可以使用它的CGImage之前發佈UIImage。

我的問題是我怎麼能直接用在另一調度隊列在主隊列定義的C指針?

+0

Duplicate http://stackoverflow.com/questions/12756295/uiimage-from-cgimageref? –

+0

在兩種不同的情況下,這是相同的原因。謝謝,該主題中的討論非常豐富! –

回答

3

你有這個問題的原因,和原因CGImageRetain()修復它,是因爲CGImage不被保留塊。這是因爲CGImageRef不是Objective-C對象指針類型。當它們是Objective-C對象指針類型時,塊僅自動保留捕獲的變量。

因此,一個替代的解決方案是簡單地讓塊捕獲它的一個「對象指針型」版本(所有核心基礎的對象可以被視爲可可Objective-C對象,反之亦然):

UIImage *uiimage = [UIImage imageWithContentsOfFile:[aPhoto completeLargeThumbFilePath]]; 

CGImageRef cgImage = uiimage.CGImage; 

id cgImageAsObject = (__bridge id)cgImage; 

dispatch_queue_t dispatchQueue = dispatch_queue_create("mediaInputQueue", NULL); 
[writerInput requestMediaDataWhenReadyOnQueue:dispatchQueue usingBlock:^{ 

    // ... unrelated stuff 
    CGImageRef cgImageAgain = (__bridge CGImageRef)cgImageAsObject; 
    CVPixelBufferRef buffer = (CVPixelBufferRef)[self pixelBufferFromCGImage:cgImageAgain size:size]; 
    // ... unrelated stuff 
}]; 
+0

感謝您的解決方案,我認爲這對於像CGImageRetain()這樣的保留方法而言更具普遍性。 –

+1

@XiaochaoYang:是的。保留在塊之外並且在塊內部釋放不是很好的內存管理實踐,因爲如果塊未運行,那麼你有泄漏;如果該塊運行不止一次,則會發生過度釋放。 – newacct

+0

哇!非常好的一點,謝謝! –

2

uiimage會被自動釋放。因此,當UIImage被自動發佈時,最有可能的是,cgImage正在被釋放。

你可以嘗試保留cgImage然後在解除阻斷它。或者你可以在塊中使用uiimage(在塊的末尾添加[uiimage self]; - 看起來很愚蠢,但有效)。

根本的問題是所謂的內部指針問題。你正在抓取一個指向對象內的某個東西的指針,但並沒有保持對這個對象的強烈引用。當物體消失時,不管內部指針指向何處,您都留下一個懸掛指針。

我這個去:

UIImage *uiimage = [UIImage imageWithContentsOfFile:[aPhoto completeLargeThumbFilePath]]; 

dispatch_queue_t dispatchQueue = dispatch_queue_create("mediaInputQueue", NULL); 
[writerInput requestMediaDataWhenReadyOnQueue:dispatchQueue usingBlock:^{ 
    CGImageRef cgImage = uiimage.CGImage; 

    // ... unrelated stuff 
    CVPixelBufferRef buffer = (CVPixelBufferRef)[self pixelBufferFromCGImage:cgImage size:size]; 
    // ... unrelated stuff 
}]; 
+0

謝謝,所以CGImageRetain()和CGImageRelease()是解決方案! –