tag:blogger.com,1999:blog-5817109634609011374.post7450639014988462866..comments2023-03-31T15:34:44.498+03:00Comments on iLessons iLearned: Some retainCount Lovejouni miettunenhttp://www.blogger.com/profile/07233375549382114547noreply@blogger.comBlogger9125tag:blogger.com,1999:blog-5817109634609011374.post-18341463787369506662011-09-09T01:26:34.917+03:002011-09-09T01:26:34.917+03:00retainCount is a horrible tool, even for debugging...retainCount is a horrible tool, even for debugging. There are a slew of much better tools available. The Allocations instrument, the static analyzer, etc...bbumhttps://www.blogger.com/profile/07733373200607345676noreply@blogger.comtag:blogger.com,1999:blog-5817109634609011374.post-30247508812552554382011-05-20T10:45:21.529+03:002011-05-20T10:45:21.529+03:00Hi jouni,
Really appreciate your update! Indeed t...Hi jouni,<br /><br />Really appreciate your update! Indeed there's nothing wrong with making mistakes, and we are here to help each others ;-)<br /><br />"Oh btw, why did I do myView = nil;? Because that speeds up crashing, in case I try to use a "released" object afterwards"<br /><br />Ok but if your program is not on a multi threaded, the problem cannot occurred (of course except programming mistakes) and if the program is multi threaded, this kind of crashes may revealed weird race conditions so setting the property to nil just "hide" the problem from you but it will not really solved it. It can be enough but it's good to understand why.<br /><br />Regards,<br />Johann Fradj from HotAppsFactoryJohann.Fradjhttps://www.blogger.com/profile/09354716009789931707noreply@blogger.comtag:blogger.com,1999:blog-5817109634609011374.post-17173227418539999242011-05-20T07:11:22.006+03:002011-05-20T07:11:22.006+03:00Oh btw, why did I do myView = nil;? Because that s...Oh btw, why did I do myView = nil;? Because that speeds up crashing, in case I try to use a "released" object afterwards. Didn't know it would also reset retain count to zero, so that was another useful lesson learned! Good to remember!jouni miettunenhttps://www.blogger.com/profile/07233375549382114547noreply@blogger.comtag:blogger.com,1999:blog-5817109634609011374.post-92177879623736030502011-05-20T06:53:13.655+03:002011-05-20T06:53:13.655+03:00Thanx Johann, checked and fixed! Removed removeFro...Thanx Johann, checked and fixed! Removed removeFromSuperview and added [myView release] in viewWillAppear.<br /><br />Instrument still says everything is ok, but I know code is now better :)jouni miettunenhttps://www.blogger.com/profile/07233375549382114547noreply@blogger.comtag:blogger.com,1999:blog-5817109634609011374.post-70327986253201189432011-05-19T17:13:00.321+03:002011-05-19T17:13:00.321+03:00"have to check them properly" Check, che..."have to check them properly" Check, check, check ;-)<br /><br /><br />"Still believe the problem was caused by not releasing myView, but saving that in property..."<br /><br />I always retained my views and almost never used viewWithTag method and I have no memory leak nor continuous over-allocation problems !<br /><br />Your code have memory leaks problems because you are retaining myView twice and only release once... So the created instance of myView remains allocated and will never be released because your are no more pointer on it ! That is the perfect definition of memory leak ;-)<br /><br />Regards,<br />Johann Fradj from HotAppsFactoryJohann.Fradjhttps://www.blogger.com/profile/09354716009789931707noreply@blogger.comtag:blogger.com,1999:blog-5817109634609011374.post-9595196468448534072011-05-19T15:44:36.149+03:002011-05-19T15:44:36.149+03:00Thanx for good comments, have to check them proper...Thanx for good comments, have to check them properly! Now just a note that a) app did have memory usage related problem (no leak, but continuous over-allocation) b) verified that with Instruments c) found a fix with retainCount and d) verified the fix with Instruments.<br /><br />Still believe the problem was caused by not releasing myView, but saving that in property...jouni miettunenhttps://www.blogger.com/profile/07233375549382114547noreply@blogger.comtag:blogger.com,1999:blog-5817109634609011374.post-8066090883513791492011-05-19T11:39:37.600+03:002011-05-19T11:39:37.600+03:00Unfortunately your code and tests are wrong...
- ...Unfortunately your code and tests are wrong...<br /><br />- (void)dealloc<br />{<br /> NSLog(@"%u", [myView retainCount]); // 3, ok<br /><br /> [self.myView removeFromSuperview]; // Strange to make a removeFromSuperview in a dealloc. When self.view will be released, it will automatically remove all its subviews<br /> NSLog(@"%u", [myView retainCount]); // 2, still ok<br /><br /> [myView release];<br /> NSLog(@"%u", [myView retainCount]); // 1, this log stating that there still is an object retaining it ! Normally if there were no memory leaks this call should crash the app because your are calling a method on a deallocated object...<br /><br /> myView = nil;<br /> NSLog(@"%u", [myView retainCount]); // 0, this log is totally wrong and will always return 0 because you are sending the method call to nil !!! Try to move the two above lines at the beginning of the method !<br /><br /> [super dealloc];<br />}<br /><br />To convince you for the myView = nil try this :<br />UIView *v = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];<br />[[[[[[v retain] retain] retain] retain] retain] retain];<br />NSLog(@"before ===> %d", [v retainCount]); // 7<br />v = nil;<br />NSLog(@"after ===> %d", [v retainCount]); // 0<br /><br />Now if myView is a retained property:<br />@property (nonatomic, retain) MyView *myView;<br />And according to your log, it seems to be !<br />Your viewWillAppear method is the source of the memory leak !<br /><br />self.myView = [[MyView alloc] initWithFrame:frame];<br />The alloc/init will create a MyView with a retain count to 1, and then your self.myView will increase the count to 2 ! (Your log confirm that !)<br />You should do <br />self.myView = [[[MyView alloc] initWithFrame:frame] autorelease];<br /><br />Moreover, I would recommend you to create your subviews in the viewDidLoad method and to not forget to implement the viewDidUnload :<br /><br />- (void)dealloc<br />{<br /> [myView release];<br /> [super dealloc];<br />}<br /><br />- (void)viewDidLoad<br />{<br /> [super viewDidLoad];<br /><br /> self.myView = [[[MyView alloc] initWithFrame:frame] autorelease];<br /> [self.view addSubview:self.myView];<br />}<br /><br />- (void)viewDidUnload<br />{<br /> [super viewDidUnload];<br /><br /> self.myView = nil;<br />}<br /><br />Finally I recommend you to use Instrument to debug memory leaks, instead of logs with retainCount.<br /><br />Regards,<br />Johann Fradj from HotAppsFactoryJohann.Fradjhttps://www.blogger.com/profile/09354716009789931707noreply@blogger.comtag:blogger.com,1999:blog-5817109634609011374.post-75516080858455772992011-05-19T06:01:45.613+03:002011-05-19T06:01:45.613+03:00The problem was that in viewWillAppear method I di...The problem was that in viewWillAppear method I didn't release myView, but kept it in property. Usually you'd do [myView release] and access it afterwards via viewWithTag, but now I "optimized". Updating that view's properties 3 times a second, while system busy doing something else... Real lesson learned: do not optimize until really needed :) Anyway, retainCount revealed the memory leak.jouni miettunenhttps://www.blogger.com/profile/07233375549382114547noreply@blogger.comtag:blogger.com,1999:blog-5817109634609011374.post-12676816920664294952011-05-18T19:00:45.814+03:002011-05-18T19:00:45.814+03:00Interesting. What is your conclusions on this deal...Interesting. What is your conclusions on this dealloc method? What if you did a myView release then myView = nil? First time I see code doing something more than just release an object in dealloc... why?Anonymoushttps://www.blogger.com/profile/09228927550994861853noreply@blogger.com