菜鸟教程小白 发表于 2022-12-12 09:31:04

ios - 为什么这个带有 ARC 的简单应用程序会泄漏?


                                            <p>所以我对 objC 编程比较陌生。但不是 C。在一个更复杂的应用程序中,我认为我有内存泄漏。我编写了这个程序只是为了进行一些测试。该应用程序非常简单:它将一系列整数存储在 MutableArray 中,这些整数表示已安排的计时器。该应用程序在当前运行循环中有一个 NSTimer,它每秒检查一次是否是将计数器与 MutableArray 的正确元素进行比较的正确时间。一切正常,但调试面板中的内存增长,增长,增长......<br>我已经尝试了一些变体,但我仍然缺少关于 ARC 的一些东西。我只是不明白,因为 ARC 不是垃圾收集器,为什么内存会增长以及我做错了什么。<br>这是代码:<br><pre><code>-(id)initWithLabel:(UILabel *)label {
    self = ;
    self.list = [init];
    self.label = label;
    return self;
}
</code></pre><br>我的类初始化函数。我将标签引用(弱,因为它是 ViewController 拥有的)传递给我的类(class)。我还分配和初始化包含 MutableArray 和其他信息(在原始应用程序中,要播放的文件,卷,eccetera)的类 mtAllarmList。<br><pre><code>-(void)ClockRun {
    NSMethodSignature * signature = ;
    NSInvocation * selector = ;
    ;
    ;

    [ addTimer: self.time = [NSTimer scheduledTimerWithTimeInterval:1
                                                                                 invocation:selector
                                                                                    repeats:YES]
                                 forMode:NSDefaultRunLoopMode];

    [ runUntilDate:[initWithTimeIntervalSinceNow: 30]];
}
</code></pre><br>ClockRun:是应用程序调用以启动一切的方法。它只是启动每秒触发的计时器来检查:<br><pre><code>-(void)check {
    self.counter++;
    int i = ;
    if(i == 1) {
      ;
    }
    else if (i == 2) {
      ;
      ;
      self.counter = 0;
    }
    else {
      initWithFormat:@&#34;controllo, %d&#34;, self.counter]];
    }
    NSLog(@&#34;controllo %d&#34;, self.counter);
}
</code></pre><br>检查:简单地对 mtAllarmList 的 方法的返回值使用react。如果定时器必须振铃,则返回 1,否则返回 0,如果序列结束则返回 2。在这种情况下 self.counter 将被设置为 0 并且 NSTimer 将无效。<br><pre><code>-(id)init {
    self = ;
    self.arrayOfAllarms = [initWithCapacity:0];
    int i;
    for(i=1;i&lt;=30;++i) {
      initWithInt:i*1]];
    }

    for(NSNumber * elemento in self.arrayOfAllarms)
      NSLog(@&#34;ho creato un array con elemento %d&#34;, );
    return self;
}
</code></pre><br>在 mtAllarmList init 方法中模拟构造一个数组(我尝试了多种模式)并记录所有元素。<br><pre><code>-(int)check:(int)second {
    int maxValue = [ intValue];
    if(maxValue == second){
      self.index = 0;
      return 2;
    } else {
      if ([ intValue] == second) {
            self.index++;
            return 1;
      } else {
            return 0;
      }
    }
}
</code></pre><br>检查方法是非常基本的,我认为不需要解释。<br><br>那么,为什么这个简单非常愚蠢的应用程序会泄漏?</p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p>由于您是在主运行循环中执行此操作,因此您可以(并且应该)简化 <code>ClockRun</code>方法:<br><pre><code>- (void)ClockRun {
    self.time = ;
}
</code></pre><br>那个<code>NSInvocation</code>代码是不必要的,<code>NSRunLoop</code>代码只能引入问题。<br><br>话虽如此,这不太可能是您内存消耗的来源。提供的代码片段中没有任何其他内容看起来像是明显的内存问题。如果您 100% 确信计时器已失效,则计时器不是问题。我想知道这个 <code>mtClockController</code> 处的 ViewController 之间的对象图.或者 ViewController 中的一些循环引用(例如,从 A 推送到 B 并再次推送到 A)。根据迄今为止提供的内容,很难说。<br><br>可悲的是,除了常规诊断之外,我们没有太多其他建议。首先,我将通过静态分析器运行应用程序(通过在 Xcode 中按 shift+command+B,或从 Xcode“产品”菜单中选择“配置文件”)。<br><br>其次,您应该通过 Leaks 和 Allocations 工具运行您的应用程序,以识别每次迭代中确切泄漏的内容。你有额外的 ViewController 实例吗?或者只是 <code>mtClockController</code> ?<br><br>除非您确定未释放的内容,否则很难对其进行补救。仪器是识别未发布内容的最佳工具。在 WWDC 2012 视频中 <a href="https://developer.apple.com/videos/wwdc/2012/index.php?id=242" rel="noreferrer noopener nofollow">iOS App Performance: Memory</a>视频的演示部分给出了使用 Instruments 的实用演示(以及大量关于内存管理的良好背景信息)。<br><br>第三,当我不确定事情是否在应该被释放的时候被释放时,我有时会包含 <code>dealloc</code>告诉我对象何时被释放的方法,例如:<br><pre><code>- (void)dealloc {
    NSLog(@&#34;%s&#34;, __PRETTY_FUNCTION__);
}
</code></pre><br>我建议这不仅适用于您的关键模型对象,也适用于您的 ViewController 。 (有时我们为我们的模型对象苦恼,只是为了意识到它是 ViewController 本身,它被其他东西保留。)<br><br>显然,Instruments 是一个更丰富的工具,但这可用于快速识别解除分配的失败(并向您展示什么是维护强引用)。<br><br>我通过 Instruments 运行你的应用程序,观察你的自定义对象,一切都被正确释放。下面,我标记了 A 代,按下按钮,让计时器到期,标记 B 代,再次按下按钮,等等。我做了四次,然后我模拟了一个内存警告,最后做了一次。一切看起来都很好(这是六个屏幕快照合二为一的汇编,显示了六代中每一代的总分配):<br><br> <img src="/image/jIhaY.png" alt="generations"/><br><br>我检查了你的世代,以及分配本身,没有你的对象在那里。一切都得到很好的释放。唯一与 <code>UIKit</code> 相关联的 Cocoa 内部对象和 <code>NSString</code> . Cocoa Touch 会在幕后缓存我们无法控制的各种内容。我做最后的“模拟器内存​​警告”的原因是让 Cocoa 有机会清除它所能清除的东西(你会看到,尽管 Generations 报告了什么,总分配量下降了一点)。<br><br>最重要的是,您的代码很好,这里没有什么可担心的。将来,不要担心在几代人中偶然出现的东西,而是专注于(a)您的类(class); (b) 任何相当大的东西。但这些都不适用于这里。<br><br>事实上,如果您使用 <code>mt</code> 限制 Instruments 仅记录您的类的信息。前缀(您可以通过停止记录仪器并点击分配图上的“i”按钮并配置“记录类型”来完成此操作),您将看到您期望的图表/世代类型:<br><br> <img src="/image/PH5SU.png" alt="mt classes only"/></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 为什么这个带有 ARC 的简单应用程序会泄漏?,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/23202727/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/23202727/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 为什么这个带有 ARC 的简单应用程序会泄漏?