簡體   English   中英

Objective-C ARC:使用塊作為C ++回調是否正確

[英]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 dataWithBytesdataWithBytesNoCopy什么區別?

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版本代碼有什么問題。

倒序:

  1. 名稱中有-dataWithBytes...-dataWithBytesNoCopy...之間的區別。 通常,如果使用原始字節數組創建NSData,則NSData會在內部復制所有字節,以便知道無法獨立修改其基礎數據(並且還可以根據需要管理內存)。 如果使用...NoCopy變體,則是在告訴NSData使用您將其傳遞給它的緩沖區作為緩沖區,而不要再分配它。 當然,這樣做的好處是不使用任何更多的內存(也許對於更大的緩沖區來說很重要),但是缺點是您需要更加小心所使用的指針以及指針之后的操作。 如果您在此處為freeWhenDone傳遞YES, freeWhenDone是在告訴NSData自身釋放后,在指針上調用free() 這假定它是直接從malloc分配的,並有效地將malloc緩沖區的所有權轉移到NSData。

  2. 您的代碼中是否有保留周期? 不,沒有明顯的一個。

因此,您所看到的取決於“泄漏”的含義,周圍代碼中正在發生的其他事情以及希望看到的東西。 您似乎正在做的是從pData獲取字節,將其復制到NSData或將其所有權轉讓給NSData,然后使用該數據創建UIImage並將其放入UIImageView 應該如何處理的內存管理NSData取決於所有權pData ,你不顯示。 (誰分配它?誰應該釋放它?何時?)。 從圖像數據創建UIImage當然會使用內存,但不會“泄漏”它。 如果您將其注釋掉,則可以肯定會使用更少的內存,但顯然不會得到圖像。 :)(NSData本身總是在-performSelector...完成之后-performSelector...釋放,因為它隨后超出范圍,在兩種情況下都將其-performSelector...緩沖區中。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM