【问题标题】:Memory mangement OS X __block variable assignement in a non-GC app非 GC 应用程序中的内存管理 OS X __block 变量分配
【发布时间】:2012-12-04 08:16:43
【问题描述】:

我有一个non-gc OS X 应用程序。在这个应用程序中,我试图从块内将一个对象分配给一个块变量。然后这个对象被另一个线程从它所在的数组中清除。我假设因为它是一个non-gc 应用程序,所以block_byref 结构正在设置BLOCK_NEEDS_FREE 标志,并且dispose 辅助函数正在清理对象。副本是否足够安全?

- (void)assignFromArray
{
  __block NSObject iWantToKeep = nil;

  [myArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
  {
    if([[obj stringVar] isEqualToString:MyStringConst])
    {
       iWantToKeep = [obj copy];
       *stop = YES;
    }
  }];

/* Assume here that the array has been cleaned up by another thread
 * and all the objects in it have been released.
 *
 * Was a copy safe enough to survive the block_byref dispose
 * and the array objects being dealloc'd so that it can be accessed here?
 */
   NSLog(@"%@", [iWantToKeep stringVar]);

  //I only need it briefly, so it can be cleaned up here
  [iWantToKeep autorelease];
}

【问题讨论】:

  • 您可以在您的区块中注销 iWantToKeep 值吗?
  • 是的,但实际的方法不是 NSLog。 NSLog 实际上被一个相当长的传递对象指针的方法所取代,所以它需要发生在块之外。
  • 你不能有NSObject类型的变量

标签: objective-c macos cocoa memory-management objective-c-blocks


【解决方案1】:

您需要先释放iWantToKeep,然后再为其分配新值,否则您将泄漏。

我不知道你为什么copying 对象。我假设你需要复制的行为。该对象只需要保留(copy 执行retain)。

副本是否足够安全,可以在 block_byref 处置中幸存下来

iWantToKeep 变量此时仍在作用域内。所以它是可用的。

以及数组对象被解除分配以便可以在此处访问?

数组不会“释放”它的元素。它释放它们。因为我们保留了我们想要的对象,所以我们拥有它并且可以使用它。

这里假设这个数组已经被另一个线程清理干净了,里面的所有对象都被释放了。

这似乎不安全。如果这发生在更早一点的迭代中,并且数组在迭代时被修改或释放,就会发生不好的事情。

【讨论】:

  • 谢谢。听起来我真正应该做的是复制数组,然后从数组中保留我想要的对象,然后处理数组副本。我不认为我在泄漏 iWantToKeep,它在方法开始时分配给 nil,我需要检查它是否存在吗? if(iWantToKeep){[iWantToKeep realease]} ?
  • @estobbart: 1) 如果你从多个线程访问数据结构,你通常需要某种锁定(例如@synchronized 会做) 2) 当你做iWantToKeep = [obj copy]; 时,你正在泄漏iWantToKeep 的前一个值,如果它不为零。这通常是正确的,与块无关。
【解决方案2】:

是的,效果很好。您只需要确保在丢弃数组之前制作了副本。

【讨论】:

  • 块调用在枚举之前是否保留在数组中?或者你可以在块执行期间改变一个数组吗?
  • 块被称为“捕获”你在其中使用的变量。对于 NSObjects,这意味着它们也会被保留。在块结束时,它们被释放。
  • 对,但是数组在被枚举的时候能变异成另一个线程吗?
  • 在枚举数组时对其进行变异会导致运行时异常。
  • 另外:永远不要假设任何 NSObject 都是线程安全的,因为它们通常不是线程安全的,因为这会导致性能损失。
猜你喜欢
  • 2011-10-09
  • 1970-01-01
  • 2013-11-21
  • 2013-09-26
  • 1970-01-01
  • 2011-01-28
  • 2012-12-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多