On Tue, Feb 10, 2009 at 3:38 PM, Seth Willits <sli...@araelium.com> wrote: > On Feb 10, 2009, at 10:30 AM, Michael Ash wrote: > >> I downloaded the example, ran it, and reproduced the crash. >> >> I then enabled zombies and ran it again. The crash message said: >> >> 2009-02-10 13:27:16.566 DocumentTest[97982:813] *** >> -[MyWindowController tableView:objectValueForTableColumn:row:]: >> message sent to deallocated instance 0x18ea40 >> >> Precisely as I had predicted. >> >> Connected it in the nib, then implemented -dealloc: >> >> >> Crash went away, again exactly as predicted. > > Right. > > The problem is that the window controller gets sent release like normal, it > release its top-level object like normal (the window), but the window does > not get deallocated because it's setOneShot:NO. The window still retains the > views, thus causing the table view to hit up the now-deallocated data > source.
A little bit of investigation shows that the object deallocation behavior is the same in both cases. Whether one-shot is checked or not, the window controller is deallocated as a direct consequence of the window closing, and the window itself gets deallocated when the autorelease pool pops at the bottom of the event loop. What's changing is that when one-shot is unchecked, the window object still exists, and still gets drawn after the window controller is destroyed. This sets you up to use that dangling pointer, a dangling pointer which in fact exists in both cases, but isn't used in the no-one-shot case. > What's "wrong" about this to me, is that setOneShot says it determines > whether or not the window *backing* is freed, not the NSWindow object > itself. So why does setOneShot:NO /seem/ to cause an extra retain on the > NSWindow? A quick test shows that either way, the retain count on the window > is 5 before [super dealloc], but clearly the window is being deallocated > after the window controller instead of before, such as when setOneShot:YES. > > The behavior of non-one shot windows is obviously not clear. Forgive me for saying this, but this sounds a lot like the common newbie complaints about Cocoa memory management. "XYZ crashes!" "That's because ABC returns an autoreleased value. "Well how was I supposed to know that? ABC ought to have a warning!" "That would be cumbersome and confusing. Instead, all methods follow the same rules, laid out here." In this case, your test case has a bug. That bug is a dangling pointer to your window controller by the table view in your window. It just so happens that you can get away with it if your window is marked as one-shot, and it just so happens that you expose the bug and crash if your window is not one-shot, due to how one-shot affects drawing. But this hardly indicates problems with the behavior of the one-shot setting. Rather, it indicates that you need to clean up dangling weak references to your objects when your objects go away, because the order of deallocation is not well defined. Think of code like this: x[0] = value; free(x); function(x[0]); That kind of code could function for a long time, and then some other change could cause it to start crashing. But it's not the change's fault, it's because this code is wrong. In short, you have a memory management problem. As is often the nature of memory management problems, it only manifested under certain circumstances. But this doesn't mean that there needs to be a special warning about those circumstances, it only means that you need to not write this kind of bug. Mike _______________________________________________ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) 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: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com