Re: KVO leaks memory
Re: KVO leaks memory
- Subject: Re: KVO leaks memory
- From: Andreas Grosam <email@hidden>
- Date: Sat, 25 Apr 2009 02:09:16 +0200
On Apr 25, 2009, at 1:07 AM, Jean-Daniel Dupas wrote:
Le 24 avr. 09 à 23:55, Andreas Grosam a écrit :
I get strange memory leaks when I use KVO. The setup of all classes
is OK as far as I can see, and the KVO is actually working. There
is no memory leak when the classes will be tested in test cases
without KVO.
There are two classes involved:
class Model and class Observer
Model has a property port where observer listens for change events.
The leak only occurs when KVO actually sends a change event.
Otherwise, there are no leaks, even when KVO is established but no
message has been sent. So it is quite probable that the source of
the leak is within KVO code. The object leaking is obviously the
receiver for the addObserver message, namely the model.
The leak is always only for one object and plus all the objects
that are retained by model, no matter how often instances of Model
will be created and KVO established.
For instance, doing this in a loop: creating observer and model,
establish KVO, then causing a KVO event, tearing down everything --
will only produce one leak from object model (plus the leaks from
retained objects).
Here is the code for the observer that adds itself as an observer
who listens at property "port" of model.
@implementation Observer
- (void) registerObserver
{
[model addObserver:self forKeyPath:@"port"
options:NSKeyValueObservingOptionNew context:NULL];
}
Here is the notification method for observer:
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary *)change context:(void
*)context
{
NSDate *date = [NSDate date];
NSString *formattedDateString = [dateFormatter
stringFromDate:date];
NSLog(@"%@: %@", formattedDateString, keyPath);
}
The model spawns a thread who's run method installs a NSTimer in
the RunLoop. The timer handler then finally changes the value of
property port of model. When the work is done, it is ensured, that
the thread exits properly and releases all retained objects. After
the thread function has been exited, the observer model and the
observer will be released.
Note: The notification method observeValueForKeyPath will be
invoked in a different thread than the main thread, where the KVO
has been established.
The application runs currently in a Unit Test as a test case from
the google toolbox for mac, on the iPhone. When the test case
finishes, all objects should be deallocated.
So, what do I see here? Any thoughts what could cause the leaks?
Do you correctly remove the observer at the end ?
[model removeObserver:self forKeyPath:@"port"];
Yes, I did check this.
It turned out that KVO is not the culprit. For some unknown reason, it
just significantly increased the chance of detecting leaks (from
roughly 1:30 to 1:1). The actual cause was this:
model creates several other objects that will be stored in a
dictionary which is also an ivar of model. The dictionary will be used
as a parameter in a recursive method invocation, where its sub
dictionaries will be processed. Well, and it seemed practically to me
(probably after a 14 hours day) to insert references to model to some
sub-dictionaries at some point of the process. Unluckily, inserting an
object increases its retain count, so the model retained itself
through the dictionary - and could never be dealloced ;)
So, once I found the error, I could fix it in 5 seconds.
Just curious, if GC would solve this kind of self-referencing issue.
Thanks anyway :)
Regards
Andreas
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden