Clang: что такое «Метод возвращает объект Objective-C с счетом удержания +0», пытаясь мне сказать? - PullRequest
3 голосов
/ 02 октября 2009

Запуск статического анализа с помощью 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 ]

12 голосов
/ 02 октября 2009

Ну .... этот код не имеет смысла.

buttonWithType: возвращает экземпляр UIButton, который уже инициализирован. Вы не должны звонить -initWithFrame: на это.

Звоните setFrame:.

Неверный код сбивает с толку анализатор.

Во-вторых, зачем прибегать к стороннему инструменту для анализа. Если вы используете Xcode 3.2 на Snow Leopard (вы должны быть - это гораздо лучшая версия Xcode, чем последний выпуск на Leopard), вы можете просто «построить и проанализировать». Все результаты анализа будут представлены в виде кода в вашем коде.

6 голосов
/ 02 октября 2009

Причина, скорее всего, заключается в отправке сообщений buttonWithType: и initWithFrame:. init* методы выполняют задачи, которые должны быть выполнены только один раз для данного объекта. Методы класса, которые создают объекты, также инициализируют их. Результатом вашего кода является повторная инициализация. Вместо этого отправьте сообщение buttonWithType, затем присвойте свойству frame.

3 голосов
/ 03 октября 2009

Имеет ли имя метода, в котором находится этот код, префикс "new"? Clang Static Analyzer следует стандартным соглашениям об именах Какао и предполагает, что метод -newSomething будет возвращать экземпляр с счетом сохранения 1. Если он видит автоматически освобожденный объект, возвращаемый таким методом, он может отображать предупреждение, которое вы видите.

0 голосов
/ 02 сентября 2011

Старый, старый, вопрос. Я с той же проблемой. Я думаю, что существующие ответы успешно объяснили, почему код неправильный, и почему анализатор говорит «+0 сохранить счет». Однако не похоже, чтобы кто-то объяснил, почему анализатор говорит, что код уменьшает счет удержания. Я думаю, я понял, почему. Это из-за того, что методы init могут возвращать объект, отличный от того, которому вы отправили сообщение. Они освободят исходный объект, выделят новый и вернут его. Анализатор предполагает, что любой метод init мог бы сделать это, хотя метод init в этом примере мог бы этого не делать.

...