Re: One Shot Windows: WARNING
Re: One Shot Windows: WARNING
- Subject: Re: One Shot Windows: WARNING
- From: Michael Ash <email@hidden>
- Date: Tue, 10 Feb 2009 13:30:52 -0500
On Tue, Feb 10, 2009 at 1:18 PM, Matt Neuburg <email@hidden> wrote:
> On Tue, 10 Feb 2009 11:12:17 -0500, Michael Ash <email@hidden>
> said:
>>On Tue, Feb 10, 2009 at 1:02 AM, Matt Neuburg <email@hidden> wrote:
>>> Actually, having looked at your example, I reproduced the crash from the
>>> bottom up by starting with the Document Architecture template.
>>>
>>> I created a window controller class, made it the Document nib's owner,
>>> overrode makeWindowControllers, put a table view in the window, made the
>>> nib's owner the table view's data source, and put code in the window
>>> controller to populate the table. Sure enough, it worked fine, but when I
>>> unchecked One Shot, it crashed if I closed the window with command-W.
>>>
>>> The crash doesn't happen if there is just an NSDocument; it has something to
>>> do with the intermediate NSWindowController. m.
>>
>>The order of object destruction in a graph such as this is not well
>>defined. You have no guarantees as to who will go first. As such,
>>whenever you have a weak reference to an object, such as the
>>dataSource outlet in a table view, you must explicitly break that weak
>>reference in your -dealloc method. If you don't, the possibility
>>exists that the table view will outlive your object *and* that it will
>>try to message it after it has gone. This is likely to be the root of
>>your problem here.
>>
>>The solution? Explicitly nil the table view's dataSource in your dealloc
> method:
>>
>>- (void)dealloc {
>> [tableView setDataSource:nil];
>> [super dealloc];
>>}
>
> That doesn't work. Did you try it? (Seth did provide a link to the actual
> example.) The problem is that nothing has been dealloced yet.
>
> The way to contribute here is to download Seth's example, run it, and see
> what you can do to prevent the crash without checking One Shot. I've tried
> to prove to myself that there's something wrong with his setup but I haven't
> managed it so far (that is why I recreated the crash starting with the stock
> document app template).
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.
I then added an outlet to the table view in the header:
@interface MyWindowController : NSWindowController {
IBOutlet NSTableView *tv;
}
Connected it in the nib, then implemented -dealloc:
- (void)dealloc
{
[tv setDataSource: nil];
[super dealloc];
}
Crash went away, again exactly as predicted.
The problem is simply that the one shot setting ends up making the
table view message its data source late in the game, after the data
source has been destroyed. This dangling pointer leads to a crash.
Tying up the dangling pointer by disconnecting the data source fixes
the crash. This is to be expected because, as I discussed, the order
of object destruction is not well defined in this case, so all weak
references need to be disconnected.
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