I take the first steps with Objective-C and run into a minor, albeit confusing problem, with the static analyzer (Product-> Analyze) in Xcode 4.1. I created a simple fraction class for rational numbers that I select and initialize, for example,
Fraction* f = [[[ Fraction alloc ] initWithNumerator:3 withDenomimator:5] autorelease]; [ f print ];
where print
is a method that just uses NSLog
to display a fraction, everything works fine. However, if I divided the alloc
/ init
construct into two statements (I understand that this is not idiomatic - I'm just trying to understand the mechanism) and use the release
manual, not autorelease
, giving:
Fraction* f = [ Fraction alloc ]; // 1. Method returns an Objective-C object with // a +1 retain count (owning reference) [ f initWithNumerator:3 withDenomimator:5]; // 2. Object released [ f print ]; // 3. Reference-counted object is used after it is released [ f release ];
the program still works without errors, but the Xcode analyzer gives warnings in the comments. Why does Xcode think that calling init
causes the object to be freed?
Thinking about this, when I ask a question, I see that my two programs are not completely equivalent, because in the first fragment my pointer f
is the result of calling init
, while in the second fragment it is the result of alloc
. Therefore, changing your code to
Fraction* a = [ Fraction alloc ]; Fraction* f = [ a initWithNumerator:3 withDenomimator:5]; [ f print ]; [ f release ];
makes it exactly equivalent, and the static analyzer stops complaining. Is it possible that init
can return a different pointer than the one that was passed to it from alloc
, and not just configure the memory in which it was passed? With this code, should you map [ a release ]
to alloc
or [ f release ]
to init
?