<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1147649206902873399</id><updated>2011-07-07T16:57:33.591-07:00</updated><category term='iOS'/><category term='memory'/><category term='debuging'/><category term='Objective C'/><title type='text'>Playing with code</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://javierhz.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1147649206902873399/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://javierhz.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>JavierHZ</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>2</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1147649206902873399.post-4255420777693319223</id><published>2010-08-13T17:33:00.000-07:00</published><updated>2011-06-03T05:20:05.767-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Objective C'/><category scheme='http://www.blogger.com/atom/ns#' term='debuging'/><category scheme='http://www.blogger.com/atom/ns#' term='iOS'/><category scheme='http://www.blogger.com/atom/ns#' term='memory'/><title type='text'>Overreleasing Objects</title><content type='html'>I'm preparing a course about iOS development and the intended pupils are all programmers so I'm looking for interesting issues to play with. One the most funniest bugs to hunt are those moving fast and unpredictably, such as those created by memory issues and threads. As my old ISP pulled off all my old contents I though it could be interesting to write here the example I prepared yesterday.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, let's go for it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;First of all let's create a new project. It never mind which kind of project (for Mac OS X or iOS) because we are speaking about Objective C, but for this post I'll use a simple view-based iPhone App.&lt;br /&gt;&lt;br /&gt;And now! I introduce you BuggyClass!!!&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:cpp"&gt;#import &amp;lt;Foundation/Foundation.h&amp;gt;&lt;br /&gt;&lt;br /&gt;@interface BuggyClass : NSObject {&lt;br /&gt;    NSString *text;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;- (NSString *)giveMeTheText;&lt;br /&gt;&lt;br /&gt;@end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Till here nothing special. Just an inoffensive class definition with a method returning an NSString and an attribute. Nice. Let's see the implementation:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:cpp"&gt;#import "BuggyClass.h"&lt;br /&gt;&lt;br /&gt;@implementation BuggyClass&lt;br /&gt;&lt;br /&gt;- (id)init {&lt;br /&gt;    if (self = [super init]) {&lt;br /&gt;        text = [[NSDate date] description];&lt;br /&gt;    }&lt;br /&gt;    return self;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;- (NSString *)giveMeTheText {&lt;br /&gt;    return text;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;- (void)dealloc {&lt;br /&gt;    [text release];&lt;br /&gt;    [super dealloc];&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Apparently an inoffensive class implementation too, though you can see the bug already if you read it.&lt;br /&gt;&lt;br /&gt;We initialize the "text" property with an NSString and we return it when asked to do so. When the object is deallocated from the memory we release everything we created... in theory.&lt;br /&gt;&lt;br /&gt;I'm omitting now all the process of creating a button with Interface Builder (Xcode 3.x and below) or Xcode 4, and binding it to an IBAction, so we goto see the code. Now, in our View Controller we could see something like this:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:cpp"&gt;#import &amp;lt;UIKit/UIKit.h&amp;gt;&lt;br /&gt;&lt;br /&gt;@interface SampleOverreleasing001ViewController : UIViewController {&lt;br /&gt; NSString *myVictimData; &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;- (IBAction)crash:(id)sender;&lt;br /&gt;&lt;br /&gt;@end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;crash: is the cute action we'll call when the button became pressed. Obviously, if the application does not crash before that (and I will do it). The innocent victim (myVictimData) is just an attribute which is going to suffer our bug although doing its job properly. Let's see the simplified code to be stressed:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:cpp"&gt;#import "SampleOverreleasing001ViewController.h"&lt;br /&gt;#import "BuggyClass.h"&lt;br /&gt;&lt;br /&gt;@implementation SampleOverreleasing001ViewController&lt;br /&gt;&lt;br /&gt;- (void)viewDidLoad {&lt;br /&gt;    [super viewDidLoad];&lt;br /&gt; &lt;br /&gt;    BuggyClass *myBuggyObject;&lt;br /&gt;    myBuggyObject = [[BuggyClass alloc] init];&lt;br /&gt; &lt;br /&gt;    myVictimData = [myBuggyObject giveMeTheText];&lt;br /&gt; &lt;br /&gt;    NSLog(@"What it should be maintained in my object is: %@", myVictimData);&lt;br /&gt;    &lt;br /&gt;    [myBuggyObject release];&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;- (IBAction)crash:(id)sender {&lt;br /&gt;    NSLog(@"Uh Ohhhh! loook at what happens with this object: %@", myVictimData);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Guess what? If you try to run this it will fail miserably. But the funny part is:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;When you use the Static Analyzer (clang) it shows it's OK.&lt;/li&gt;&lt;li&gt;When you use Instruments it doesn't show memory leaks -well, that's true ;)&lt;/li&gt;&lt;li&gt;If you enable NSZombies you get a hint, but not much.&lt;/li&gt;&lt;li&gt;If this were a multithreaded environment and our BuggyClass were on another thread or NSOperation this could be crazy.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;So, lets see. You already know what's happening, don't you? Yeah, you read the title of the post: overreleasing an object so, somewhere, we are creating a memory issue. Well, actually Xcode give us the key too:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_3JXq69we72s/TGXysjWB3hI/AAAAAAAAAAM/VubShYbEuJw/s1600/Captura+de+pantalla+2010-08-14+a+las+03.33.12.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_3JXq69we72s/TGXysjWB3hI/AAAAAAAAAAM/VubShYbEuJw/s320/Captura+de+pantalla+2010-08-14+a+las+03.33.12.png" /&gt;&lt;/a&gt;&lt;/div&gt;Yes!&amp;nbsp;&lt;span class="Apple-style-span" style="color: #0a8700; font-family: Menlo; font-size: 11px;"&gt;Program received signal:&amp;nbsp; “EXC_BAD_ACCESS”&lt;/span&gt;&amp;nbsp;means that we are trying to use memory out of our control. So let's play with the code to understand what happened and many other variations.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Case 1: The code as is&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The problem here is clear, but if you are new to Objective C probably you missed it. Look, when we store the value of text doing:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:cpp"&gt;text = [[NSDate date] description];&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;actually we are pointing to an autoreleased object. This means that when Cocoa Touch (in this case) finds a drain message to the NSAutoreleasePool of the proper run loop, the retain count is decremented. In this case, as there's no other retain message, the object is deallocated. In other words, when you have an autoreleased object you have to expect it to be autoreleased sometime (nobody can say exactly when).&lt;br /&gt;&lt;br /&gt;But that's not only the one problem. If you look at few lines below you'll see:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:cpp"&gt;[text release];&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And, as you can suppose, that's more than enough. In fact, it's too much releasing. The retain count for text (or the object pointed by text) was 1, after autoreleasing it it could be 0, but sending another release is illegal. We can not dealloc something already deallocated. Which deallocation is done before? the release or the autorelease? Well, if you are a good observer I put a trace on the previous screenshot to give you a hint. So, looking at the stack trace on the left and following the code you can see easily that release was called on first step and then it was autorelease (that's why&amp;nbsp;the crashed object is kinda&amp;nbsp;UIApplicationMain).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Case 2: overautoreleasing&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;What if we would written&lt;br /&gt;&lt;pre class="brush:cpp"&gt;[text autorelease];&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;instead of&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:cpp"&gt;[text release];&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;You may think the problem is the same and the error message is the same too. But that's not true. In this case you will receive the message:&amp;nbsp;&lt;span class="Apple-style-span" style="color: #0a8700; font-family: Menlo; font-size: 11px;"&gt;Program received signal:&amp;nbsp; “SIGABRT”.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Probably here Xcode is much more clear. You'll receive a message in the log similar to the next one:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;sampleOverreleasing001(12641,0x3e7037c8) malloc: *** error for object 0x140560: double free&lt;br /&gt;*** set a breakpoint in malloc_error_break to debug&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I think it's clear enough. Just pass to the next case.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Case 3: retaining the overreleased&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Let's go again to the first case when we were doing:&lt;br /&gt;&lt;pre class="brush:cpp"&gt;[text release];&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: #3f1281; font-family: Menlo; font-size: 11px;"&gt;&lt;span style="color: black;"&gt;[&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #3f1281; font-family: Menlo; font-size: 11px;"&gt;&lt;span style="color: #538187;"&gt;text&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #3f1281; font-family: Menlo; font-size: 11px;"&gt;&lt;span style="color: black;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #3f1281; font-family: Menlo; font-size: 11px;"&gt;release&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #3f1281; font-family: Menlo; font-size: 11px;"&gt;&lt;span style="color: black;"&gt;];&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Suppose you know the problem is related to your victim object because you were using NSZombies. You can be tempted of retaining the problematic NSString. So you would do:&lt;br /&gt;&lt;pre class="brush:cpp"&gt;myVictimData = [[myBuggyObject giveMeTheText] retain];&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;instead of:&lt;br /&gt;&lt;pre class="brush:cpp"&gt;myVictimData = [myBuggyObject giveMeTheText];&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Do you really think this is a good idea? Run the program and cry with me. One, two, three...&lt;br /&gt;... mmmm ... it didn't crashed!&lt;br /&gt;&lt;br /&gt;So, you have the great idea of pressing the button on the screen. That button invoking crash: and all you happiness fall down immediately: finally it crashed with the expected message:&amp;nbsp;&lt;span class="Apple-style-span" style="color: #0a8700; font-family: Menlo; font-size: 11px;"&gt;Program received signal:&amp;nbsp; “EXC_BAD_ACCESS”&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Now the problem is again an overreleased object but with a little difference. In case 1 we tried to release a deallocated object, now we are trying to load data from the deallocated object. It's not the same thing, but very close.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Case 4: retaining the overautoreleased&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;This is the last case we'll see now, I promise. Now we are going to retain again the NSString returned by myBuggyObject but starting from the case 2 (when we autoreleased the text).&lt;br /&gt;&lt;br /&gt;This case is, perhaps, the most interesting. This case depends a lot on the run loops and the execution order. This sample is too simple but a complex multithreaded environment may convert this case in a nightmare.&lt;br /&gt;&lt;br /&gt;Do you think it will crash? Fine! not at the beginning. So we press the button to call crash: and... Great! It didn't crash neither. But here it is the worse thing. It didn't crash but if you see the console... well look at it:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;2010-08-14 04:19:07.071 sampleOverreleasing001[12687:307] What it should be maintained in my object is: 2010-08-14 04:19:07 +0200&lt;br /&gt;2010-08-14 04:19:07.077 sampleOverreleasing001[12687:307] BuggyClass dealloc&lt;br /&gt;2010-08-14 04:19:48.213 sampleOverreleasing001[12687:307] Uh Ohhhh! loook at what happens with this object: ko.lproj&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;What's that! "ko.lproj"???? Your pointer is pointing to an unexpected part of the memory. As a result this kind of issue could be changing from execution to execution: sometimes it will generate exceptions (if you send a message it doesn't respond); other times you'll receive apparently good values (bad ones actually); other times you could receive unexpected results... that's not so easy to debug and for sure in a complex development it wont be funny.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The solution&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Well, you know the best solution: Retain the initially autoreleased object as in:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:cpp"&gt;text = [[[NSDate date] description] retain];&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Exercise for hackers&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Hackers as those described by &lt;a href="http://en.wikipedia.org/wiki/Hacker_(computing)"&gt;Steven Levy&lt;/a&gt;, between others, understand me. Not criminals.&lt;br /&gt;&lt;br /&gt;You now know a way of accessing memory beyond the strict limits you usually stay. May you find something interesting poking around? Tell us!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;b&gt;Note to me&lt;/b&gt;&lt;/i&gt;: next time name the BuggyClass as InnocentClass, KakklsfdQznjkr or something like that. These guys had too much meaningful names this time. ;)&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1147649206902873399-4255420777693319223?l=javierhz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1147649206902873399/posts/default/4255420777693319223'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1147649206902873399/posts/default/4255420777693319223'/><link rel='alternate' type='text/html' href='http://javierhz.blogspot.com/2010/08/overreleasing-objects.html' title='Overreleasing Objects'/><author><name>JavierHZ</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_3JXq69we72s/TGXysjWB3hI/AAAAAAAAAAM/VubShYbEuJw/s72-c/Captura+de+pantalla+2010-08-14+a+las+03.33.12.png' height='72' width='72'/></entry><entry><id>tag:blogger.com,1999:blog-1147649206902873399.post-3197962115551349095</id><published>2010-08-02T10:25:00.000-07:00</published><updated>2010-08-02T10:31:25.053-07:00</updated><title type='text'>The Empty Blog</title><content type='html'>Sorry, I changed my ISP and they deleted all my files and entries. So this will be "The Empty Blog" till I have enough time to restore my backups.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In the meantime, if you need any of the file I used to link from my blog (JavierHZ's Blog) just post a comment.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Sorry for the inconveniences.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1147649206902873399-3197962115551349095?l=javierhz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1147649206902873399/posts/default/3197962115551349095'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1147649206902873399/posts/default/3197962115551349095'/><link rel='alternate' type='text/html' href='http://javierhz.blogspot.com/2010/08/empty-blog.html' title='The Empty Blog'/><author><name>JavierHZ</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry></feed>
