Accessor method object management? - objective-c

After reading the Memory Management Guide I am trying to get my head around what is happening here My understanding "so far" is ...
- (EngineClass *)engine {
return [[engine retain] autorelease];
}
I am returning a pointer to an Engine object.
The retain count of the object is incremented to record we are making a new pointer to the object
Balance the above retain by specifying an autorelease at some future point.
Am I on the right track?
cheers -gary-

I'm not sure I'd say the retain is "to record we are making a new pointer to the object."
The retain-autorelease pair is there to indicate that there's another object interested in the return value, so it needs to stick around at least that long, but the other object doesn't properly own the return value. Without the retain, if the object performing this method is deallocated immediately afterward, the engine might not have any other owners and would also be deallocated immediately. That's not the expected behavior. Doing it this way causes the object's ownership not to go away until the autorelease pool is drained.

Related

Potential Leak of Object stored into a NSMutable dictionary (GPUImageFramework) iOS 8+

I am new to Objective C, and I would really appreciate any help resolving a memory leak. I am trying to resolve memory management issues that occur in the GPUImageFramework.
In the method below I am getting the following messages highlighted in blue:
Method returns an Objective-C object with a +1 retain count
Object leaked: allocated object is not referenced later in this execution path and has a retain count of+1
-(void)setAndExecuteUniformStateCallbackAtIndex:(GLint)uniform forProgram:(GLProgram *)shaderProgram toBlock:(dispatch_block_t)uniformStateBlock;
{
[uniformStateRestorationBlocks setObject:[uniformStateBlock copy] forKey:[NSNumber numberWithInt:uniform]];
uniformStateBlock();
}
enter image description here
I take it that the method being stored in the NSMutable dictionary needs to be released into memory.
Please can somebody point me in the right direction?
I have ARC enabled within the GPUImageFramework
You either need to enable it for your project, not just for the framework, or you need to handle memory management manually.
The sub-expression [uniformStateBlock copy] returns an object with, in the language of the error, "+1 retain count"; i.e. an object the caller "owns" and which the caller must release.
When your code inserts an object into the array the array itself also takes ownership, i.e. does a retain. It does not take ownership from the caller, it is still left owning the block returned by copy and it is this ownership which is never relinquished which results in the leak, as the error states.
If you enable ARC it will take care of this and release the callers ownership of the block at the appropriate point.
Otherwise you can leave ARC off and insert a release call when the caller no longer requires the block (which still leaves the array with ownership).
HTH

why [self.property release] will cause the static analyzer to show an "incorrect decrement of the reference count" error? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Incorrect decrement of the reference count of an object that is not owned at this point by the caller
Why shouldn't I use the getter to release a property in objective-c?
So, I get that using [self.myProperty release] is discouraged (Apple itself recommends not to). Although it appears to me that it COULD lead to problems in some cases, not all cases. Is this correct? More importantly: I don't get why using a syntax like [self.myProperty release] in my -dealloc method(s) will cause the static analyzer to show an "incorrect decrement" error. Despite any other reason discouraging such a syntax, my class still owns its properties (which I have declared with "nonatomic,retain") so why the warning?
I've been reading several posts on this but it seems I can't really wrap my mind around it.
Some of them go into details about the possible side effects of using such a syntax, but what I really want to know is the reason behind the "incorrect decrement" error.
Any help would greatly be appreciated.
Cocoa memory management has a concept of "ownership" which is expressed most succinctly in the rule: If you call new or alloc, or send retain or copy to an object, you own the result, and are responsible for sending release when you're done with it. Otherwise, you do not own it, and you must not send release.
Instance variables, basically by definition, contain objects that the instance owns. You need the objects to be valid for the life of the instance, so you create them with an ownership-granting method in init:
// myDinkus and creationDate are ivars of whatever class this is.
// They are assigned to with owned references.
myDinkus = [[Dinkus alloc] init]; // ownership due to alloc
creationDate = [[NSDate date] retain]; // ownership due to retain
These now need to be sent release when the instance is done with them; generally speaking, this will be in dealloc.
Getter methods don't return owning references. This is the way it should be; when your code, e.g., asks a label for its font color, it doesn't need that color object to stick around. Or if it does, it must explicitly take ownership by sending retain. Giving it ownership by default would create headaches at best and possibly leaks.
That established, [self.myProperty release] causes the static analyzer to complain because it's a violation of the ownership concept. The object returned from [self myProperty] isn't owned by the caller. The fact that it just so happens to be the same object as an ivar that is owned by the caller is irrelevant. (In fact, it might not be the same; the getter might return a copy of the object it represents, for example. It might construct an entirely new value based on a group of ivars. It's even possible for there to be no ivar that corresponds to a getter.)
Since objects which are not owned must not be sent release, doing so to the result of a getter is incorrect.
There are other, practical, reasons not to do this (covered quite well, especially by Justin's answer in the question proposed as dupe), but that's the reason the analyzer is complaining.
Fundamentally, you're sending a release message to an object that you haven't sent a retain to (at least not explicitly). The static analyzer will expect to see balanced retain/releases.
When you declare your property as nonatomic,retain you are handing responsibility for releasing the value to the property's setter.
If you do a [self.myProperty release] then your property still contains its old value and any subsequent setting of that property will do a release on that old value - but you've already released it, so now it is over-released... Hence the warning.
To release the value you should use self.myProperty = nil - the setter will release the old value and assign nil to the property.

Objective C: Memory Leak in non-void instance method

I am getting another memory leak in a non-void instance method that returns a object of class NSMutableArray.
Can someone advise me on how I can fix this leak? I tried to release 'userFollowings' at the end of the method but it's still reporting a leak.
When your are to return an object from a method in which you have either initialized it or retained it, it is common practice to return it autoreleased. That way, the user receiving the object doesn't have to worry about releasing it. So, your final line of code should look like this:
return [userFollowing autorelease];
It probably wouldn't hurt to read a little from the Memory Management Programming Guide to catch up on memory management rules such as this, and there are plenty of other helpful resources out on the web and on this site.
There are a set of conventions used by Cocoa programs that make memory management much less error prone. When a method returns an object, the code that calls it needs to know if it owns it or not.
What it boils down to is that if you are writing a method that returns an object and that method doesn't convey ownership upon the caller by being named something like new, alloc, copy, etc., you need to autorelease it before you return it.
That's what the message you are getting is talking about - "Object returned to caller as an owning reference" means that you're conveying ownership on the calling code. The problem is that your method name indicates otherwise.
If I were to call your method and needed to hang onto the object, I'd call retain on it so that I owned it. I need to do this because your method name implied I wasn't the owner. So long as you are returning an autoreleased object, that's correct. But if you don't autorelease the object, it will end up with a retain count of 2 - once when you allocated it and once when I retained it. When I finally get round to releasing it, it will still have a retain count of 1, and will never be deallocated from memory, resulting in a memory leak.
The problem is that userFollowings never gets released. Try ending with
return [userFollowings autorelease];
Try this:
NSMutableArray* userfollwings = [[[NSMutableArray alloc] init] autorelease]

About dealloc/release: is it always OK to do x = nil; [x release]; - or can it cause problems?

since every assignment to a variable with a different object increases its retain count and in the dealloc its not always clear how often a variable got assigned a simple [maVar release] might NOT BE SUFFICIENT. So using ALWAYS myVar = nil sets the retain count to zero, and a subsequent [myVar release] will never cause a problem again. (is it actually still required ?)
The only situation when not to do it this way is if myVar is passed OUT then I must not do this, since the value gets destroyed by myVar = nil;
Is my thinking correct? Or could this way of avoiding leaks cause any other problems?
Your thinking is incorrect in quite a lot of ways. These are probably just scratching the surface:
Assignment to a variable does not increase its retain count. (There are some subtleties to do with properties, but frankly that's way beyond the level we're at here.)
dealloc is called when the retain count reaches 0.
Setting myVar = nil does not affect the retain count.
myVar = nil destroys only the local pointer value, it does not destroy an object that has been passed out.
It is safe to call [myVar release] when myVar is nil, but it isn't useful -- it does nothing.
Worrying about retain counts is always a mistake. Worry about what you own.
It is clear that your grasp of C pointers and Objective-C memory management is a bit lacking. I'd suggest doing some remedial C work before several thorough re-reads of the Memory Management docs.
Please read Apple's documentation on Memory Management.
Assigning a pointer to an object will not increment the retain count, only calling retain does that. Functions with Copy or Init in the name should return an object with a retain count of 1, other functions should return autoreleased objects that will be dealloc'd when the main loop finishes.
Setting an object to nil doesn't modify the retain count, but it will cause that memory to leak. Calling release on the pointer at that point essentially does nothing. You need to be responsible about using retain, release, autorelease, and how you name your functions if you want to effectively manage your memory usage.

What is the difference between releasing and autoreleasing?

I still have some unclear understand about release and autorelease. What are the difference between both of them? I have this code. For facebook connection. I crash it sometimes when I go to Facebook login, I doubting maybe it is because I don't release the object nicely.? Thanks for any helps
if (_session.isConnected) {
[_session logout];
} else {
FBLoginDialog* dialog = [[[FBLoginDialog alloc] initWithSession:_session] autorelease];
[dialog show];
}
The Memory Management Programming Guide for Cocoa will soon be your best friend. In brief, object instances in Cocoa are memory managed using reference counting (unless, of course you're using garbage collection on OS X). An object indicates that it wants to 'retain' an ownership interest in an other instance--keep it from being deallocated--by sending it a -retain message. An object indicates that it wants to release that interest by sending the other instance a -release message. If the number of objects that have 'retained' and ownership interest in an object drops to 0 (i.e. when the last of the owning instances sends a -release message), the instance with a 0 retain count is deallocated.
It's sometimes convenient to say "I want this instance to be released some time in the future". That's the purpose of -autorelease. Sending an -autorelease message adds the receiver to the current NSAutoreleasePool. When that pool is drained, it sends a -release message to all the instances in the pool. An NSAutoreleasePool is automatically created at the start of each iteration of each thread's run loop and drained at the end of that iteration. Thus, you can do something like this in a method:
- (id)myMethod {
return [[[MyObject alloc] init] autorelease];
}
The caller of this method will get back an instance that they can -retain if they wish to keep it. If they don't retain it, it will stick around at least until the enclosing autorelease pool is drained:
- (void)someOtherMethod {
...
id instance = [obj myMethod];
... // do more with instance, knowing that it won't be dealloc'd until after someOtherMethod returns
}
Releasing means you release that right away.
Autoreleasing means you want the variable to be released on the next autorelease pool.
You use autorelease when you want to keep retaining the variable but don't want to create a memory leak. You use release when you don't need the variable anymore.
Sample:
- (NSNumber *)return5 {
NSNumber * result = [[NSNumber alloc]initWitnInt: 5];
[result autorelease];
return result;
}
Why do we use autorelease there?
If we use [result release] instead, variable result will be destroyed AT that time. Which means that the returned value will be garbage.
If we do not release at all, variable result will be hold FOREVER incurring memory leak.
We can tell every caller to the function to release result but that would be a headache and prone to error.
So we use autorelease. We mark the variable to be released on the next autorelease pool. Basically we mark the variable to be released near the alloc. Hence the mantra alloc is paired with release in the same function holds all the time.
Actually, you'll do fine changing all release into autorelease. Your memory use won't be efficient, however, the effect is minimal. All variables, in all programming language is effectively autoreleased.
Anyway, use ARC.
background discussion:
objective-c is reference counted, so objects are deleted when the reference count reaches 0. release reduces the reference-count immediately, autorelease reduces it when the autorelease-pool is popped
when to use:
use autorelease when allocating the object if
you do not need it after the current function
it will be retiained by some other objet/function and will be released by a later by the retaining code
when the logic of the current function is tricky, so you would have to send release in a dozen different places before doing a return
use "manual" release
to revert a previous retain (in case you are implementing a library)
if you need precise control of freeing objects (e.g. they use lots of memory or the autorelease pool will not be popped for some time)
but really my freand:
read the Memory Management Programming Guide for Cocoa as suggested by Barry and run your code with instruments (zombies and leaks) often to catch any and almost all memory management errors.
Erik
According to the Memory Management Programming Guide for Cocoa:
The autorelease method, defined by
NSObject, marks the receiver for later
release. By autoreleasing an
object—that is, by sending it an
autorelease message—you declare that
you don't want to own the object
beyond the scope in which you sent
autorelease.
Also:
The autorelease method thus allows
every object to use other objects
without worrying about disposing of
them.