Как предотвратить автоматическое сохранение / освобождение при вызове сообщения Obj-C с C ?

#objective-c #ios5 #objective-c #automatic-ref-counting #xcode4.2

#objective-c #ios5 #objective-c #автоматический подсчет ссылок #xcode4.2

Вопрос:

У меня есть такой код:

 @interface MyTimer : NSObject
- (int)getValue;
@end

@interface TimerHolder : NSObject {
    ExternalControl* m_externalControl;
}
@property (retain, nonatomic) MyTimer* timer;
@end

class ExternalControl {
    __unsafe_unretained TimerHolder* m_holder;
public:
    ExternalControl(TimerHolder* holder) : m_holder(holder);
    int getTimer() { return [m_holder.timer getValue] };
};
  

Метод ExternalControl::getTimer() вызывается очень часто. Во время профилирования я заметил, что во время вызова getTimer() obc-j также вызывает objc_retain and objc_release (предположительно для m_holder или m_holder.timer), что в конечном итоге отнимает много времени! Удаление __unsafe_unretained не имело значения.

По конструкции я знаю, что при ExternalControl::getTimer() каждом вызове m_holder и его таймер будут оставаться активными в течение всего времени вызова, поэтому я думаю, что сохранение / освобождение не требуется.

Есть ли какой-либо способ предотвратить их вызов?

Я использую XCode 4.2 с iOS 5 SDK с включенной ARC. Отвечает ли ARC и его удаление приведет к удалению сохранения / освобождения? (Я не хотел тратить время на повторное создание проекта без ARC, просто чтобы проверить это, прежде чем проверять с вами, друзья мои!)

Комментарии:

1. Мне кажется, что этот код нарушает одно из правил ARC, а именно: не хранить указатели извлечения в структурах C (класс C в данном случае считается структурой C). Таким образом, правильный ответ, вероятно, не использовать ARC для этого файла. developer.apple.com/library/ios/#releasenotes/ObjectiveC /…

2. Почему бы не написать свой ответ как ответ вместо комментария?

3. Я не могу вспомнить, почему нет. Возможно, я не чувствовал, что это правильно ответило на вопрос. В то время я не занимался программированием ARC.

Ответ №1:

Я могу говорить только из опыта, не связанного с ARC, поскольку я еще не использовал его (и не планировал, что это старая школа).

Однако у меня есть несколько проектов, использующих библиотеку C и сохраняющих ссылки на нее в коде obj-C. Я точно знаю, что сохранение / освобождение не вызывается, если явно не запрошено.

Кстати, я не мог использовать Obj-C при связывании библиотеки C и вместо этого должен был использовать Obj-C , иначе конструктор / деструкторы C вызывались не так, как ожидалось. Это был просто вопрос переименования файла .m в .mm

Надеюсь, это поможет.

Комментарии:

1. Спасибо, это, похоже, указывает на ARC как на виновника. Да, я использую Obj-C .

2. Удалена ARC, дополнительные сохранения / освобождения исчезли.

Ответ №2:

Если вы хотите вручную обработать сохранение / освобождение только для этого класса (отключите ARC). установите флаг компилятора «-fno-objc-arc» на вкладке «Этапы сборки» для этого исходного файла.

Ответ №3:

В сеансах WWDC 2011 на ARC специально упоминается, что при компиляции для отладки сохранение / освобождение ARC не оптимизируется.

Если вы этого не сделали, попробуйте запустить свой код в режиме выпуска и профилировать его. Вы должны увидеть существенную разницу.

Однако я знаю, что ARC не учитывает предположения о дизайне, которые вы подразумеваете, когда говорите «По конструкции». Но ARC не должен касаться вашей переменной экземпляра «__unsafe_unretained»… вы уверены, что этим вызовам сохранения / освобождения передается указатель на это?

Комментарии:

1. Я только что проверил, и схема «Профиль» по умолчанию строится в режиме выпуска. Так что я предполагаю, что они не оптимизируют это конкретное мое использование… Что кажется достаточно справедливым, поскольку нет гарантии, что мой код на C не мог выполняться, пока объект Obj-C был / уничтожается, поэтому они не могут просто удалить эти сохранения / освобождения, если я не могу каким-то образом сообщить компилятору о своих намерениях.

2. Но ваш «__unsafe_unretained» сообщает ему о ваших намерениях… Я был бы шокирован , узнав, что ARC пытался сохранить / освободить это … такое поведение нарушило бы контракт, который вы с ним установили. Здесь происходит что-то еще.

3. Из того, что я понимаю, __unsafe_unretained сообщает компилятору, что эта переменная содержит указатель, и что этот указатель не будет автоматически обнуляться, если указатель уничтожен. Поэтому имеет смысл, что компилятор пытается защитить пользователя, сохраняя объект, тем самым предотвращая выпуски во время его использования. Моим намерением было бы сообщить компилятору что-то вроде «__unsafe_retained», в котором я знаю , что объект должен быть сохранен где-то в другом месте, поэтому нет необходимости сохранять его для меня, пожалуйста. 🙂

4. То, что вы хотите , это то, что он делает. Если бы это был я, я бы не отказался от использования ARC так легко… Я думаю, вам было бы полезно выяснить, что происходит на самом деле и как это исправить. developer.apple.com/videos/wwdc/2011 «Введение в автоматический подсчет ссылок» — слайд № 45 — описывается __unsafe_unretained следующим образом: • Like a traditional variable, or an assign property • Not initialized • No extra logic • No restrictions поведение , которое вы описываете , — это то , чего strong нет __unsafe_unretained . Видео явно проясняет это.

5. Я все еще сомневаюсь в вашем утверждении (или, может быть, слайд не совсем корректен !?). Чтение mikeash.com/pyblog / … говорит мне, что strong это означает «сохраненный и обнуляющийся (т. Е. Указатель становится 0 при уничтожении ссылки)», weak означает «не сохраненный, но обнуляющийся», __unsafe_unretained означает «не сохраненный и не обнуляющийся». Все это не говорит о том, что ObjC может не добавлять пару сохранения / освобождения вокруг вызова сообщения, которая может быть оптимизирована, если компилятор точно знает, что объект сохранен, как в случае с strong .