[英]Objective-C ARC: is it correct to use a block as C++ callback
我有一個用C ++和Objective-C編寫的應用程序。 C ++部分從遠程攝像機接收數據,然后調用Objective-C回調(塊)進行顯示。 Objective-C已啟用ARC。
當加載顯示視圖時,我在C ++部分設置了一個塊,當數據到來時,C ++將調用此塊來更新顯示。
代碼如下:
- (void)viewDidLoad
{
__weak CameraVC *weakSelf = self;
self.callback_func = ^int(int iWidth, int iHeight, int iDataLen, void *pData) {
NSData *data = [NSData dataWithBytes:pData length:iDataLen];
[weakSelf performSelectorOnMainThread:@selector(updateDisplayWithData:)
withObject:data waitUntilDone:YES];
return 0;
};
setDisplayCallback(self.callback_func);
}
- (void)updateDisplayWithData:(NSData *)data
{
self.imageView.image = [UIImage imageWithData:data];
}
setDisplayCallback()
是用於設置回調的C ++函數。
當應用程序運行時,在xcode面板中顯示應用程序的內存使用量,並且始終在增加,數小時后,應用程序崩潰了,我認為這是內存泄漏嗎?
我試圖注釋代碼:
// self.imageView.image = [UIImage imageWithData:data];
內存泄漏已停止。
問題1是否有保留周期導致此內存泄漏?
我嘗試從以下位置替換代碼塊:
self.callback_func = ^int(int iWidth, int iHeight, int iDataLen, void *pData) {
NSData *data = [NSData dataWithBytes:pData length:iDataLen];
[weakSelf performSelectorOnMainThread:@selector(updateDisplayWithData:)
withObject:data waitUntilDone:YES];
return 0;
};
至:
self.callback_func = ^int(int iWidth, int iHeight, int iDataLen, void *pData) {
NSData *data = [NSData dataWithBytesNoCopy:pData length:iDataLen freeWhenDone:YES];
[weakSelf performSelectorOnMainThread:@selector(updateDisplayWithData:)
withObject:data waitUntilDone:YES];
return 0;
};
內存泄漏的問題減少了,但仍然存在。
問題2 dataWithBytes
和dataWithBytesNoCopy
什么區別?
UPDATE
我嘗試設置沒有ARC的單個文件,然后修改代碼:
- (void)viewDidLoad
{
self.callback_func = ^int(int iWidth, int iHeight, int iDataLen, void *pData) {
@autoreleasepool {
NSData *data = [NSData dataWithBytes:pData length:iDataLen];
[self performSelectorOnMainThread:@selector(updateDisplayWithData:)
withObject:data waitUntilDone:YES];
}
return 0;
};
setDisplayCallback(self.callback_func);
}
內存使用情況穩定。 我很好奇我的ARC版本代碼有什么問題。
倒序:
名稱中有-dataWithBytes...
和-dataWithBytesNoCopy...
之間的區別。 通常,如果使用原始字節數組創建NSData,則NSData會在內部復制所有字節,以便知道無法獨立修改其基礎數據(並且還可以根據需要管理內存)。 如果使用...NoCopy
變體,則是在告訴NSData使用您將其傳遞給它的緩沖區作為緩沖區,而不要再分配它。 當然,這樣做的好處是不使用任何更多的內存(也許對於更大的緩沖區來說很重要),但是缺點是您需要更加小心所使用的指針以及指針之后的操作。 如果您在此處為freeWhenDone
傳遞YES, freeWhenDone
是在告訴NSData自身釋放后,在指針上調用free()
。 這假定它是直接從malloc
分配的,並有效地將malloc緩沖區的所有權轉移到NSData。
您的代碼中是否有保留周期? 不,沒有明顯的一個。
因此,您所看到的取決於“泄漏”的含義,周圍代碼中正在發生的其他事情以及希望看到的東西。 您似乎正在做的是從pData
獲取字節,將其復制到NSData或將其所有權轉讓給NSData,然后使用該數據創建UIImage
並將其放入UIImageView
。 你應該如何處理的內存管理NSData
取決於所有權pData
,你不顯示。 (誰分配它?誰應該釋放它?何時?)。 從圖像數據創建UIImage當然會使用內存,但不會“泄漏”它。 如果您將其注釋掉,則可以肯定會使用更少的內存,但顯然不會得到圖像。 :)(NSData本身總是在-performSelector...
完成之后-performSelector...
釋放,因為它隨后超出范圍,在兩種情況下都將其-performSelector...
緩沖區中。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.