iPhone, Object allocated and stored into 'glossPath' is not referenced later (object leaked) - objective-c

I have this warning in analyzer and also in leaks instrument, how can I fix this leak?
Object allocated on line 86 and stored into 'glossPath' is not referenced later in this execution path and has a retain count of +1 (object leaked)
Tnx

You are responsible for releasing the object returned by CGPathCreateMutable() as per "The Create Rule". It is also stated in the reference:
Return Value
A new mutable path. You are responsible for releasing this object.
You can use CGPathRelease() to release the path.
CGPathRelease(glossPath);

Related

"performSelector may cause a leak" alternative when it DOES leak?

I have to perform a selector by name on a Class (not an instance) and use its return value:
id obj = [objClass performSelector:NSSelectorFromString(methodName) withObject:p1];
The selector creates a new instance of the Class. I need to use the returned instance. Obviously I get the usual performSelector may cause a leak because its selector is unknown warning since this project is compiled with ARC.
If I understand correctly (from the answers here and others), in this instance the performSelector will cause a leak (do correct me if I'm wrong, then I could just disable the warning and be done with it). The selectors are implemented as follows:
+ (id) objectWithFile:(NSString*)p1
{
return [NSKeyedUnarchiver unarchiveObjectWithFile:p1];
}
What are my options when I have to use selector from string and the selector creates and returns a new instance of the object?
I considered NSInvocation but its getReturnValue method requires me to provide my own allocated buffer in which the return value is stored. I'm not sure if this even works with ARC and class methods, or whether I simply have to __bridge_transfer cast the malloc'ed return value buffer to id and that's all there is to it.
objectWithFile: is not a method of the "alloc, copy, init, mutableCopy, and new family"
and therefore is
a "Unretained return values" method in the sense of the "Clang/ARC documentation":
A method or function which returns a retainable object type but does
not return a retained value must ensure that the object is still valid
across the return boundary.
...
In the worst case, this may involve an autorelease, but callers must
not assume that the value is actually in the autorelease pool.
So no matter what you do inside the method, the caller does not have to release the
returned object.
Therefore I don't think that you have a memory leak in your code.

How to resolve 'Potential Leak' issue

I am using the 'analyze' tool in xcode to check for potential leakages in my app.
I am getting the following warning as a result.
How do I resolve the potential leak shown above? "self.answerArray" is just an array I declared in my header file
You've called mutableCopy on the array (which returns a new array with a retain count of +1 - You own it), and you assign it to a property (which I assume is a strong/retain property) and you're not releasing it. You're leaking the memory.
You should release tempArray after assigning it to the property - and ensure the property is released in your class' dealloc method.
You should either send retain/release to answerArray (release old object before assigning a new one, retain the new object), or, probably better, declare a property
#property (retain) NSArray* answerArray;
this way compiler will generate release/retain (on assign) for you. See documentation. Otherwise the object answerArray was referencing before the assignment (answerArray = tempArray) will remain dangling in memory.
In case you will use a declared property, make sure to add your temp variable to autorelease pool:
tempArray = [[self.answerArray mutableCopy]autorelease];
or just send it release yourself (right before it goes out of scope).

Objective C: Returning Objects from Methods

I'm learning how to program, and starting off with Objective C. I'm trying to understand exactly what happens when an object is allocated from within a method.
-(Fraction *) add: (Fraction *) f
{ //'result' will store the result of the addition
Fraction *result = [[Fraction alloc]init];
result.numerator = (numerator*f.denominator + denominator*f.numerator);
result.denominator = denominator*f.denominator;
[result reduce];
return result;
}
I understand that I can create an object to store 'result' in when it is returned,
tempStorageObject = [aFraction add: bFraction];
and that i am then responsible for releasing it, but what happens when I don't store it, as in:
[aFraction add: bFraction];
NSLog(#"%i/%i", result.numerator, result.denominator); //result object not declared in main
I am told that I have an undeclared identifier. I get that, but what exactly happens to 'result' after using my 'add' method. Where does it go? Shouldn't I be able to access its variables since it was created and returned in the method? Obviously not, but I'm not clear on why. I've tried re-reading my book and searching this forum but I can't find a clear answer. Thanks. (First post)
Four different things:
Properties
Local variables
Function return values
Heap storage
"I get that, but what exactly happens to 'result' after using my 'add' method. Where does it go?"
It's a local variable. It's gone.
"Shouldn't I be able to access its variables"
Seeing your comment, it looks like you mean access by dot notation. No, dot notation is for properties.
"since it was created"
Dot notation does not give you access to local variables.
"and returned in the method?"
Dot notation does not give you access to function return values.
All of the first three things are pointers, when they refer to objects. The fourth thing is what they point to. When you do alloc, you create an object in heap storage. You then have instance variables, properties, local variables, and function return values refer to the heap storage. In a way you think of them as being the same thing as the object in heap storage. Syntactic sugar like dot notation helps you do that. Your object will last, but in this case the different variables that refer to it are limited in scope and come and go.
When you call alloc, an object is created on the heap.
When you assign it to result, result now has the same object.
When you return result, the local variable result no longer exists, the return value temporarily holds the same object, and the object still exists in the heap.
4a. When you assign the function result to tempStorageObject, another local variable (I guess), the function result goes away. It existed only temporarily to pass a value from inside the function to out. tempStorageObject now holds the object, and the object still exists in the heap.
4b. Instead if you don't assign the function result to anything, then the function result still goes away. But the object still exists on the heap. You have a problem. You have an object on the heap, but you can't refer to it directly there (unless you are good at guessing its address). Without being able to refer to it, you can't get it off the heap, which will be a major problem if you do that kind of thing over and over. The heap will start to get full with objects you can't get rid of and you'll run out of memory. That's what's called a leak.
The correct thing to do in this case is to return [result autorelease]. When you call [something autorelease], it adds "something" to an "autorelease pool" and then returns the same something.
You call alloc and create an object on the heap. Its retain count starts at 1.
You assign it to result, a local variable. Result has the object and it's on the heap.
[result autorelease]. result has the object, it's in an autorelease pool, and it's on the heap.
return that. result is gone, the return value has the object, it's in the autorelease pool, and it's on the heap.
5a. Assign the return value to tempStorageObject. The return value is gone, tempStorageObject has the object, it's in an autorelease pool, and it's on the heap.
6a. You leave the scope of tempStorageObject. tempStorage object is gone. The object is in an autorelease pool and on the heap.
5b. You don't assign the function result to anything. The function result is gone. The object is in an autorelease pool and on the heap.
7ab. The autorelease pool is drained. That is usually done from code in the main run loop provided by the system library, but you can do it yourself if you know how. All the objects in the autorelease pool, including the one we're paying attention to, are sent a release message. The object's retain count goes to 0.
8ab. With a retain count of 0, the object is removed from the heap. The object is in the autorelease pool.
9ab. The second thing drain does is remove all the objects from the pool. Now the object doesn't exist anywhere anymore.
You said you are familiar with release, so I just say you should use autorelease keyword, which releases the allocated object when no more code blocks need it, check document below, from Apple:
Memory Management Programming
The scope of alloc is global: once you have allocated an object, there is room for it in memory and that memory will remain allocated until the release count hits zero (or the app is terminated). Until then, the object will still exist.
The scope of a variable is much shorter. In your example 'result' goes out of scope right at the end of the method 'add'. But that variable is just a name, a reference to an object. So whoever is calling add, should make sure to do something with the returned object. Otherwise there is no more variable referring to the object and so it can not be released.

XCode Analyzer Warnings Without Details / Line Numbers

I ran the analyzer and found a handful of warnings that I can't associate with lines in the code. I'm not sure how to handle them. Clicking on them brings me to the right file in the editor, but the analyzer summary results tell me that much. I don't know what each of these is referring to, and going through the code line-by-line is not productive (I don't know what I'm looking for).
Object with +0 retain counts returned to caller where a +1 (owning) retain count is expected
Incorrect decrement of the reference count of an object that is not owned at this point by the caller
Object with +0 retain counts returned to caller where a +1 (owning) retain count is expected
Object sent -autorelease too many times
For the last warning, I removed the autorelease, and it went away, but I don't know how to release it, since it's used in a return statement.
- (Client*) createNewClient {
...
Client *client = [NSEntityDescription insertNewObjectForEntityForName:#"Client"inManagedObjectContext:dataInterface.managedObjectContext];
...
return client;
}
What do I do with these, in general?
As you are not owning the object that is returned by insertNewObjectForEntityForName:, you do not have to release it.
From the Apple Memory Management Programming Guide:
You take ownership of an object if you
create it using a method whose name
begins with “alloc”, “new”, “copy”, or
“mutableCopy” (for example, alloc,
newObject, or mutableCopy), or if you
send it a retain message.
insertNewObjectForEntityForName: contains 'New', but does not begin with it.
this may be a flagged for naming conventions. if you want to return an autoreleased object, try renaming it to:
- (Client *)clientWithCurrentContext

Why retain a static variable?

Isn't it unnecessary to retain a static variable since it stays around for the duration of the program, no matter if you release it?
See this code:
https://github.com/magicalpanda/MagicalRecord/blob/master/Source/Categories/NSManagedObjectContext+MagicalRecord.m#L24-29
I'm assuming you mean a static object pointer, such as static NSString *foobar;.
Such variables indeed have a lifetime as long as the application, but the variables we're talking about are pointers only. In Objective-C, objects are always dynamically allocated, and so we always address them with a pointer to their type, but the underlying data for an object is still present out in the dynamically allocated wild blue yonder.
You must still retain the object because, while the pointer to the object will never go out of scope, the object itself can be deallocated just like any other object, and so your pointer will end up pointing to garbage, or worse, another unrelated object.
A simplified version of Jonathan Grynspan's accepted answer:
The retain isn't for the variable which points to an object. That variable will last forever because it's static. The retain is for the object the variable points to. Without the retain the object could (and should) be deallocated. Then you've got a variable pointing to a thing which will cause a sigabrt. This variable pointing nowhere is known as a "dangling pointer."
For the ARC context, the best thing to do is declare the static variable as strong, so something like this:
static ThatClass * __strong thatStaticVariable;
This ensures that the object that thatStaticVariable points to will be a valid object (i.e., never gets deallocated) once assigned. However, you don't actually need the __strong keyword at all, because it's the default (so sayeth the docs, thanks to #zpasternack), so just use
static ThatClass *thatStaticVariable;
and you're good.
Note: forever = while the application is running