【问题标题】:Dealing with infinite loops in Objective C在 Objective C 中处理无限循环
【发布时间】:2011-12-13 01:08:09
【问题描述】:

我最近加入了一个 iPad 项目。在查看代码库时,我遇到了一些不寻常的事情,其中​​之一是(我已经对其进行了元编码):

while (something.isAlwaysTrue) {
    // Wait for something to happen. i.e. Get data from an internet connection.
    // Respond to something.
}

在我开始对应用程序进行内存分析并发现这些循环大量内存泄漏之前,我没有注意到这有任何问题。原因是因为它们永远不会结束,所以在其中创建的任何 autorelease 实例永远不会被释放,因为该方法永远不会结束并且自动释放池永远不会有机会释放。

在与编写代码的开发人员讨论后,我想出了以下技术:

-(void) queueTask {
    // Using GCD or perform with delay, call the process method.
}

-(void) process {

    // Wait and/or do stuff. 

    [self queueTask];
}

基本思想是通过使用一种方法通过 GCD 或 runloop 进行排队,它使自动释放池有机会执行和清理autorelease 实例。这似乎工作得很好。

我的问题是 - 这是处理这些循环的最佳方法吗?或者有更好的方法吗?

【问题讨论】:

    标签: objective-c ios memory-leaks


    【解决方案1】:

    两点;

    最小化堆增长

    无论如何,以下是最小化内存增长的方法:

    while (something.isAlwaysTrue) {
      NSAutoreleasePool * pool = [NSAutoreleasePool new];
      // Wait for something to happen. i.e. Get data from an internet connection.
      // Respond to something.
      [pool release], pool = 0;
    }
    

    或者,如果您更喜欢咩咩(原文如此)的边缘:

    while (something.isAlwaysTrue) {
      @autoreleasepool{
        // Wait for something to happen. i.e. Get data from an internet connection.
        // Respond to something.
      }
    }
    

    自动释放池就像线程本地堆栈一样运行。当你推送一个池时,自动释放的对象被添加到当前线程的顶部池中。当您弹出池时,池会为每个自动释放发送 release 消息。

    使用 GCD 代替自动释放池很奇怪;类似于使用单个字符 NSStrings 的 NSArray,您应该简单地使用单个 NSString

    多线程程序流程

    无限循环是一个非常可疑的程序。它表明您可能正在尝试重新发明运行循环。主运行循环当然很常见。辅助线程 1) 具有运行循环 2) 永不结束是不寻常的。

    您应该重新考虑程序的流程。通常,您对事件采取行动,而不是屏住呼吸,轮询直到它们完成。您可能正试图在您提议的计划中摆脱这种情况——但我没有足够的细节。

    【讨论】:

    • 完全正确。我建议@autoreleasepool,然后如果你切换到 ARC,那么该方法就准备好了。
    • 不幸的是,这个无限循环是开发人员在很多地方放置的东西。我喜欢嵌入自动释放池的想法。我没有这样的想法。特别是在等待来自服务器的数据的循环中。该架构正在维护连接并等待服务器决定向其发送内容。可能是秒,也可能是分钟。考虑到我读到的关于自动发布的内容,我首先想到的是 GCD。我同意无限循环闻起来很糟糕。这就是我开始研究这些代码部分的原因。
    • @drekka +1 进行调查。当前使用的方法很容易破坏系统。我不太了解要求或执行,但是(假设您必须轮询)它可能有助于重新实现所有这些无限循环,而是将它们全部集中到一个类似NSOperationQueue 的东西中。理想情况下(在大多数情况下),该队列将是串行的,这样轮询就不会耗尽资源。尽管如此,请求永远不会结束,它们不会从循环中中断,不会取消,(续)
    • (cont) 并且依赖的实现无法影响请求的流程(我可能假设太多)。该系统还将受益于对超时请求的延迟重试。该实现至少会编组请求,因为问题(无限期等待)不会从并行化中受益。串行轮询也很有可能会执行并且感觉更快,因为总体上对资源的竞争较少。串行轮询是可疑的,但该方法会改善大多数符合要求的情况。
    猜你喜欢
    • 2012-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多