Cocoa naming scheme for assignment initializer

For some reason, I thought it was really in accordance with the memory management naming rules:

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

However, now I run my static analysis, he thinks there is a potential leak every time I did this.

I see that there is __attribute((ns_consumed)) that I could use in a fooWithNewBar . But Xcode 4.0.1 Clang does not yet support this attribute.

So there is no such naming pattern?

+4
source share
5 answers

I also think that in your case there is no naming pattern matching ns_consumed . Name templates are mainly based on NeXTSTEP / Apple, and I cannot come up with a method within apples with the same semantics that you want.

Note that you can tell Xcode to use the newer version of Clang Static Analyzer , which supports the ns_consumed attribute, which was released with checker-254 .

I am using checker-256 (released today, but any version> = 254 should work), and Ive just tried the following:

 // 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 

and

 // 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 

This code gives the static analyzer a warning about a potential leak of a string stored in s :

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

whereas this code, which uses a method parameter with the ns_consumed attribute, does not give a static analyzer warning:

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

There is no such template. Wherever I thought, I read about it, I did not.

+1
source
 Bar *bar = [Bar new]; 

Do you have a bar.

 [Foo fooWithNewBar:bar]; 

If it wants its own bar, it must save it. This will not give up your property, so you still have to release the panel.

I have never seen the template you are using.

0
source

Foo has shown interest in Bar, but * bar is still interested until [bar release] is interested.

-1
source

Property in Objective-C memory management with counting is a C ++ style of share_ptr , not auto_ptr . In other words, you are not transferring ownership of the instance of Foo . Rather, the Foo instance declares the ownerhsip share in your Bar instance (leaving you as the caller [Bar new] with the ownership share). You should always give up your share of ownership of an instance before it can be released. So your example should be

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

Please note that you must use -autorelease rather than -release to give up your equity because Foo needs the opportunity to claim a share of the property before Bar is released.

-1
source

Source: https://habr.com/ru/post/1347925/


All Articles