4

我在 NSArray 上写了一个方便的方法,它类似于 PHP 的 list() 函数,用于将数组“解包”为不同的对象:

- (void)unpackInto:(__strong id *)obj1, ...
{
    __strong id *idPtr;
    va_list args;
    va_start(args, obj1);

    idPtr = obj1;
    NSUInteger idx = 0;
    NSUInteger count = [self count];
    while (idPtr != NULL && idx < count) {
        *idPtr = [self objectAtIndex:idx];

        // Increment the args and idx count
        idx++;
        idPtr = va_arg(args, __strong id *);
    }
}

我最初__autoreleasing id *遇到了 EXC_BAD_ACCESS 问题,但当在具有自己的自动释放池的线程上调用此方法(实际上是两次,如果重要的话)以将内容解压缩到临时本地堆栈变量中时,我遇到了 EXC_BAD_ACCESS 问题。当主线程出现并尝试(再次)自动释放内容时,EXC_BAD_ACCESS 被抛出。

在这种情况下,谁能帮助我遵循这些桥接参数的逻辑?我担心这__strong会导致稍微不那么明显但同样邪恶的孪生表亲:内存泄漏......

4

1 回答 1

2

我还没有看到您的源代码,但是如果您考虑所有权而不是保留/释放/自动释放池,则可以解决大多数 ARC 问题的答案。尝试回答,谁拥有数组,谁拥有解压后的指针。如果我理解正确,您的调用方法看起来像这样

  NSArray *arr = [NSArray arrayWithObjects:@"a", @"b", @"c", @"d", nil];

  NSString *a, *b, *c, *d;
  [arr unpackInto:&a, &b, &c, &d, nil];

在访问解压缩变量之前,您的数组是否已释放?请记住, __autoreleasing 不会将值“保留”到变量参数指针上。所以如果你的数组被释放,你的指针就会变成垃圾。我的猜测,你的 EXC_BAD_ACCESS 是因为你的主数组被释放了。

当您通过引用返回时,不应使用 __strong。它不会增加保留计数。没有办法让ARC知道,这些变量要在调用方法中释放。因此 ARC 在其作用域之后发布它们。将分配的对象传递给调用方法并让调用方法解除分配的唯一方法是从属于 init 系列的方法中返回它。当您跨方法边界返回值时,ARC 使用方法族(或宏 NS_RETURNS_RETAINED/NS_RETURNS_NON-RETAINED)来确定谁“拥有”指针。

如果传递 const 指针(非写回指针),则可以使用 __strong 进行引用传递。事实上,对于没有所有权限定符的 const 指针,隐含了 __strong。

更多关于 LLVM 文档的信息在这里 http://clang.llvm.org/docs/AutomaticReferenceCounting.html#ownership.restrictions.pass_by_writeback

于 2012-02-26T02:01:28.960 回答