Схема именования какао для назначения инициализатора - PullRequest
4 голосов
/ 13 апреля 2011

По какой-то причине я думал, что это допустимо в соответствии с правилами именования управления памятью:

Bar *bar = [Bar new];
[Foo fooWithNewBar:bar];
// no need to release bar, foo took ownership

Однако сейчас я выполняю свой статический анализ, и он думает, что при каждой такой попытке возникает потенциальная утечка.

Я вижу, что есть __attribute((ns_consumed)), который я мог бы использовать в объявлении fooWithNewBar.Но Clang в Xcode 4.0.1 пока не поддерживает этот атрибут.

Итак, такого шаблона именования нет?

Ответы [ 5 ]

5 голосов
/ 14 апреля 2011

Я также думаю, что в вашем случае нет шаблона именования, соответствующего ns_consumed. Шаблоны именования в значительной степени определяются NeXTSTEP / Apple, и я не могу придумать метод в средах Apple с той же семантикой, которую вы хотите.

Обратите внимание, однако, что вы можете указать Xcode использовать более свежую версию Clang Static Analyzer , которая поддерживает атрибут ns_consumed, который был выпущен с checker-254 .

Я использую checker-256 (выпущен сегодня, но любая версия> = 254 должна работать), и я только что попробовал следующее:

// MyClass.h
#ifndef __has_feature      // Optional.
#define __has_feature(x) 0 // Compatibility with non-clang compilers.
#endif

#ifndef NS_CONSUMED
#if __has_feature(attribute_ns_consumed)
#define NS_CONSUMED __attribute__((ns_consumed))
#else
#define NS_CONSUMED
#endif
#endif

@interface MyClass : NSObject {
@private
    NSString *_string;
}
+ (MyClass *)myClassWithNewStringConsumed:(NSString *) NS_CONSUMED string NS_RETURNS_RETAINED;
+ (MyClass *)myClassWithNewString:(NSString *)string NS_RETURNS_RETAINED;
@end

и

// MyClass.m
#import "MyClass.h"

@implementation MyClass

+ (MyClass *)myClassWithNewStringConsumed:(NSString *)string {
    MyClass *o = [MyClass new];
    if (o) o->_string = string;
    return o;
}

+ (MyClass *)myClassWithNewString:(NSString *)string {
    MyClass *o = [MyClass new];
    if (o) o->_string = string;
    return o;
}

@end

Этот код выдает предупреждение статического анализатора о потенциальной утечке строки, хранящейся в s:

// SomewhereElse.m
NSString *s = [[NSString alloc] initWithFormat:@"%d",
    [[NSProcessInfo processInfo] processIdentifier]];
MyClass *o = [MyClass myClassWithNewString:s];
[o release];

, тогда как этот код, который использует параметр метода с атрибутом ns_consumed, не выдает предупреждение статического анализатора:

// SomewhereElse.m
NSString *s = [[NSString alloc] initWithFormat:@"%d",
    [[NSProcessInfo processInfo] processIdentifier]];
MyClass *o = [MyClass myClassWithNewStringConsumed:s];
[o release];
1 голос
/ 13 апреля 2011

Нет такой картины.Где бы я ни читал об этом, я не читал.

0 голосов
/ 13 апреля 2011

Владение в Objective-C подсчетом ссылок для управления памятью - C ++ share_ptr, а не auto_ptr стиль. Другими словами, вы не передаете право собственности на экземпляр Foo. Скорее, экземпляр Foo объявляет долю ownerhsip в вашем экземпляре Bar (оставляя вас и вызывающего абонента [Bar new] с долей владения). Вы всегда должны отказаться от своей доли владения экземпляром, прежде чем он может быть освобожден. Таким образом, ваш пример должен быть

Bar *bar = [[Bar alloc] init]; //Most Obj-C devs prefer alloc/init. When in Rome...
[Foo fooWithNewBar:[bar autorelease]]; //relinquish ownership of bar

Обратите внимание, что вы должны использовать -autorelease вместо -release, чтобы отказаться от своей доли владения, потому что Foo требуется шанс получить долю владения до того, как bar будет освобожден.

0 голосов
/ 13 апреля 2011
Bar *bar = [Bar new];

У вас есть бар.

[Foo fooWithNewBar:bar];

Если для этого нужен собственный бар, он должен сохранить его. Это не лишает вас права собственности, поэтому вам все равно придется отпустить панель.

Я никогда не видел шаблон, который вы используете.

0 голосов
/ 13 апреля 2011

Foo заинтересовался Bar, но * bar все еще имеет интерес до [bar release] этого интереса.

...