繁体   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