Как выбрать спецификатор моста ARC для указателей на указатель объекта (id *)? - PullRequest
4 голосов
/ 25 февраля 2012

Я написал небольшой удобный метод для 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 был брошен.

Может ли кто-нибудь помочь мне следовать логике с этими параметрами моста в этом случае? Я обеспокоен тем, что __strong приведет к чуть менее очевидному, но не менее злому кузену-близнецу: утечка памяти ...

1 Ответ

2 голосов
/ 26 февраля 2012

Я не видел ваш исходный код, но ответы на большинство проблем 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), чтобы определить, кто «владеет» указателем.

Вы можете использовать __strong для передачи по ссылке, если передаете constуказатель (указатели без обратной записи) На самом деле, для указателей на константы без квалификаторов владения подразумевается __strong.

Подробнее об этом в документации LLVM здесь http://clang.llvm.org/docs/AutomaticReferenceCounting.html#ownership.restrictions.pass_by_writeback

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...