【问题标题】:Memory leak in |NSArray objectEnumerator|?|NSArray objectEnumerator| 中的内存泄漏?
【发布时间】:2012-04-16 05:51:16
【问题描述】:

以下线程解释了如何找到当前包含鼠标光标的屏幕:

http://www.cocoabuilder.com/archive/cocoa/104529-current-mouse-screen.html

- (NSScreen *)currentScreenForPointUsingEnumeration:(NSPoint)aPoint
{
    NSEnumerator *screenEnumerator = [[NSScreen screens] objectEnumerator];
    NSScreen *screen;
    while ((screen = [screenEnumerator nextObject]) && !NSMouseInRect(aPoint, screen.frame, NO));

    return screen;
}

我在每次鼠标移动时都会运行它。

不幸的是,使用 Xcode 的 Instruments 工具中的“分配”功能,上面的代码显示了许多 NSFastEnumeration 的分配。

分析器中没有出现“泄漏”,但分配计数不断增加且从未减少。该应用程序的整体内存使用量也在继续上升。

使用for(...) 循环的类似函数没有相同的问题。

我可以做些什么来提高这里的性能吗?或者这是我不应该担心的事情?

编辑:

顺便说一句,尝试[[[NSScreen screens] objectEnumerator] autorelease] 会使应用程序崩溃并完全锁定我的鼠标。无法单击或以其他方式找出退出应用程序或 Xcode 的方法。需要重新启动 OS X。所以不要那样做。

【问题讨论】:

  • “Xcode 的分析工具”是指 Instruments 吗? Instruments 与 Clang 静态分析器有很大的不同,静态分析器无法检测到运行时堆积的私有实现细节对象,因为运行时还没有发生。
  • 对,Instruments的“Allocations”工具。我将编辑问题。
  • objectEnumerator 不返回您拥有的对象;你可以通过它的名字来告诉它。因此,向该对象发送autorelease 是错误的。

标签: objective-c xcode cocoa memory-management


【解决方案1】:

我可以做些什么来提高这里的性能吗?

我不确定您为什么认为存在性能问题。分析仪显示没有泄漏,所以除非它有问题(不幸的是,这些天并非不可能),否则可能没有泄漏。

如果您将代码包装在自动释放池中,NSFastEnumerations 应该会被释放。

【讨论】:

  • 来自问题:“......分配计数一直在增加并且永远不会减少。”这不是严格意义上的“泄漏”,而是内存使用问题。 You can use Instruments to detect it,我认为这是提问者所做的(尽管他错误地将其称为“分析器”)。
【解决方案2】:

你可以尝试两件事;不确定哪个会有所帮助,或者他们是否会有所帮助。

一、使用实际的快速枚举语法:

for( NSScreen * screen in [NSScreen screens] ){
    if( NSMouseInRect(aPoint, screen.frame, NO) ){
        return screen;
    }
}

或者将其包装在您自己的自动释放池中,以帮助创建的数组和枚举器对象尽快释放。

NSScreen *screen = nil;
@autoreleasepool{
    NSEnumerator *screenEnumerator = [[NSScreen screens] objectEnumerator];
    while ((screen = [screenEnumerator nextObject]) && !NSMouseInRect(aPoint, screen.frame, NO));
    [screen retain];    // Ensure screen sticks around past return; only under MRR
}
return [screen autorelease];

【讨论】:

    【解决方案3】:

    您可以尝试使用块,和/或将其包装在自动释放池中,例如:

    __block NSScreen *retVal = nil;
    [[NSScreen screens] enumerateObjectsWithOptions:NSEnumerationConcurrent 
         usingBlock:^(Screen *scrn, NSUInteger idx, BOOL *stop) {
             if (NSMouseInRect(aPoint, scrn.frame, NO)) {
               retVal = scrn;
               *stop = YES;
         }];
    return retVal;
    

    【讨论】:

      猜你喜欢
      • 2011-10-04
      • 2011-10-13
      • 1970-01-01
      • 1970-01-01
      • 2012-06-16
      • 1970-01-01
      • 1970-01-01
      • 2011-05-31
      • 2012-08-16
      相关资源
      最近更新 更多