在 ARC 中使用 Blocks 和以某种方式复制的奇怪内存泄漏

Posted

技术标签:

【中文标题】在 ARC 中使用 Blocks 和以某种方式复制的奇怪内存泄漏【英文标题】:Weird memory leak with Blocks and copying in certain way in ARC 【发布时间】:2013-04-28 14:01:00 【问题描述】:

以下简单代码在 ARC 下,在最新的 Xcode (4.6.2) 中使用 Leaks 工具进行分析,在 ios 模拟器中,在具有 -Os 优化的发布构建配置中显示泄漏:

- (BOOL)application:(UIApplication *)application
  didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

    for (int i = 0; i < 10; i++)
    
        void (^block)() = ^
        
            NSLog(@"%d", i);
        ;

        id x = block;
        [x copy];
    

    return YES;

它显示了 10 个泄露的块。 (它不会显示关闭优化的泄漏;但关闭优化对我们的应用程序来说是不现实的。)奇怪的是,查看每个泄漏块的内存管理历史记录,它们看起来都很好——每个都有一个 malloc从副本和发布;但不知何故释放不会释放它?

这是一个编译器错误(它使用的是默认的 Apple LLVM 编译器)吗?

【问题讨论】:

您确定 ARC 已开启吗?尝试插入-retain 看看编译器是否报错。 @KevinBallard:是的,ARC 已开启。如果 ARC 没有打开,为什么关闭优化后泄漏会消失?另外,如 Instruments 中所见,该块已释放;它只是没有被释放。 如果将id x = block; [x copy]; 替换为[block copy] 会发生什么? @Ríomhaire:它消失了。它必须是分配给id的块类型,其他任何东西都不会重现它 【参考方案1】:

这似乎是编译器中的错误或泄漏工具,我不确定是哪个。您应该向 Apple 提交错误。

将代码缩短为以下代码时也会发生相同的泄漏:

int i = 0;
void (^block)() = ^
    int y = i;
;

id x = block;

仅当块引用父作用域中的局部变量时才会出现泄漏。

您看到这种情况发生在实际生产代码中还是仅在本示例中?

【讨论】:

以上是关于在 ARC 中使用 Blocks 和以某种方式复制的奇怪内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

带有块、ARC 和非 ARC 的 Objective C 内存管理

Code::Blocks 给了我某种权限错误

在 iOS 应用程序的生命周期中何时触发 ARC? [复制]

JSF 2.0 在整个会话中从浏览器和以编程方式设置区域设置 [重复]

objective-c启用ARC时的内存管理 (循环引用)

Spark SQL - 隐式创建模式和以编程方式创建模式之间的确切区别