Clang: что такое "Метод возвращает объект Objective-C с счетом удержания +0", пытаясь мне сказать?
Выполняя статический анализ с помощью clang в XCode 3.2 и инструменте анализа Никиты Жука, я часто сталкивался с этой парой предупреждений:
Метод возвращает объект Objective-C с +0 счетом сохранения (ссылка не принадлежит)
Неправильное уменьшение счетчика ссылок объекта на данный момент не принадлежит вызывающей стороне
Пример кода, который может вызвать это предупреждение:
UIButton* button = [[UIButton buttonWithType:UIButtonTypeCustom] initWithFrame: CGRectMake(x, y, width, height)];
return button;
Я предположил, что кнопки, созданные таким образом, автоматически высвобождаются, как и любой другой объект NSObject, созданный с помощью удобного фабричного метода. Поэтому я возвращаю его, и вызывающий абонент может решить, сохранить его или нет. В чем проблема с этим?
Обязан ли я сохранять и автоматически освобождать объект перед его возвратом? И самое главное, может ли это предупреждение быть предупреждением когда-либо быть причиной страшных аварий, связанных с выбросами?
Теперь я понимаю, что это происходит только с кнопками UIB. Это из-за того, что это кластер классов?
РЕДАКТИРОВАТЬ: фрагмент ниже показывает минимальный случай, когда Clang выдает эти предупреждения (с предупреждениями, выделенными жирным шрифтом). Оба предупреждения отмечены в операторе, создающем объект (buttonWithType:
сообщение).
-(UIButton*) ztupidTezt:(UIImage*) img
{
UIButton* bt = [[UIButton buttonWithType:UIButtonTypeCustom]initWithFrame:
1 Метод возвращает объект Objective-C с счетом сохранения +0 (ссылка не принадлежит)
2 Неправильное уменьшение счетчика ссылок объекта на данный момент не принадлежит вызывающей стороне.
CGRectMake(0.0f, 0.0f, img.size.width, img.size.height)];
bt setImage:img forState:UIControlStateNormal];
return bt;
}
4 ответа
Причина, скорее всего, заключается в использовании отправки как buttonWithType:
а также initWithFrame:
сообщение. init*
методы выполняют задачи, которые должны быть выполнены только один раз для данного объекта. Методы класса, которые создают объекты, также инициализируют их. Результатом вашего кода является повторная инициализация. Вместо этого отправьте buttonWithType
сообщение, затем назначьте frame
имущество.
Ну.... этот код не имеет смысла.
buttonWithType:
возвращает экземпляр UIButton, который уже инициализирован. Вы не должны звонить -initWithFrame:
в теме.
Вызов setFrame:
,
Плохой код сбивает с толку анализатор.
Во-вторых, зачем использовать сторонний инструмент для анализа. Если вы используете Xcode 3.2 на Snow Leopard (вы должны быть - это значительно лучшая версия Xcode, чем последний выпуск на Leopard), вы можете просто "построить и проанализировать". Все результаты анализа будут представлены в виде кода вашего кода.
У имени метода, у которого есть этот код в нем, есть "новый" как префикс? Clang Static Analyzer следует стандартным соглашениям об именах Какао и предполагает, что метод -newSomething будет возвращать экземпляр с сохраняемым счетчиком 1. Если он видит автоматически освобожденный объект, возвращаемый таким методом, он может отображать предупреждение, которое вы видите.
Старый, старый, вопрос. Я с той же проблемой. Я думаю, что существующие ответы успешно объяснили, почему код неправильный, и почему анализатор говорит "+0 сохранить счет". Однако не похоже, чтобы кто-то объяснил, почему анализатор говорит, что код уменьшает счет удержания. Я думаю, я понял, почему. Это из-за того, что методы init могут возвращать объект, отличный от того, которому вы отправили сообщение. Они освободят исходный объект, выделят новый и вернут его. Анализатор предполагает, что любой метод init мог бы сделать такую вещь, хотя метод init в этом примере не может.