Re: One Shot Windows: WARNING
Re: One Shot Windows: WARNING
- Subject: Re: One Shot Windows: WARNING
- From: Michael Ash <email@hidden>
- Date: Wed, 11 Feb 2009 00:12:26 -0500
On Tue, Feb 10, 2009 at 3:38 PM, Seth Willits <email@hidden> 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 (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