I\'m making my first steps with Objective-C and have encountered a minor, albeit confusing issue with the static analyzer (Product->Analyze) in XCode 4.1. I have created a
So is it possible that
init
can return a different pointer than the one passed to it fromalloc
, rather than just configuring the memory it has been passed?
Yes, that's exactly it. This is also the reason why you don't just call [super init]
in your initialisers; instead you call it and assign the result to self
because you aren't necessarily going to get the same instance back.
The relevant documentation is in The Objective-C Programming Language.
With this code should I pair
[ a release ]
with thealloc
or[ f release ]
with theinit
?
If you really want to do something like that, you'd have to check that they aren't equal first, otherwise you'd be over-releasing. But the real solution is to not split up alloc
and init
. That's the idiomatic way of instantiating objects in Objective C and doing it a different way that you have to add extra code for is counterproductive.
Trying to separate calls to +alloc
and -init
is explicitly recommended against by Apple, per the documentation for +[NSObject alloc]
:
An init... method must be used to complete the initialization process. For example:
TheClass *newObject = [[TheClass alloc] init];
and -[NSObject init]
:
In some cases, an init method might release the new object and return a substitute. Programs should therefore always use the object returned by init, and not necessarily the one returned by alloc or allocWithZone:, in subsequent code.
The static analyzer is complaining because it expects that +alloc
will be paired with -init
. Because -init
can release the sender, the static analyzer therefore thinks you're trying to call a method on a deallocated instance.
So is it possible that init can return a different pointer than the one passed to it from alloc, rather than just configuring the memory it has been passed?
absolutely.
With this code should I pair [ a release ] with the alloc or [ f release ] with the init?
you would assign the value of the initialized object to f
(as you have). at this point, a
may be a dangling pointer (if another address is returned). thereore, f
should be release
d.
the explanation for this order is that the object may have opted to return a specialized version/variant of itself, and this reallocation happens along the init...
chain.
silly demonstration:
@interface Fraction : NSObject
{
@private
int numerator;
int denominator;
}
@end
static Fraction* EvilFraction = ...;
@implementation Fraction
- (id)initWithNumerator:(int)num denominator:(int)den
{
self = [super init];
if (nil != self) {
if (0 == den){
[self release];
return [EvilFraction retain];
}
}
return self;
}
@end