Re: Crash in NSPersistentDocument writeToURL:ofType:forSaveOperation:originalContentsURL:error:
Re: Crash in NSPersistentDocument writeToURL:ofType:forSaveOperation:originalContentsURL:error:
- Subject: Re: Crash in NSPersistentDocument writeToURL:ofType:forSaveOperation:originalContentsURL:error:
- From: Quincey Morris <email@hidden>
- Date: Thu, 27 Jan 2011 12:08:48 -0800
On Jan 27, 2011, at 05:36, Jim Thomason wrote:
> No, not quite. More accurately I was assuming that error is explicitly
> a pointer to nil upon entry (or, I suppose, a pointer to some other
> valid NSError that appeared from somewhere and was handed through to
> us).
I was a bit sloppy in my terminology earlier. The 'NSError**' parameter is a C "simulation" of passing a 'NSError*' variable *by address* -- all C can do is pass an address, and that's not quite the same thing semantically. The 'NSError*' variable, if regarded as being passed by address, is output only, which means that its value on entry is trash.
> So basically the important thing is that setting error to something
> (even a nil, at a minimum) is required if writeToURL:... returns NO.
> Which makes sense if the input pointer could be garbage. And
> specifically, the fix that I came up with of explicitly setting *error
> = nil is the proper fix.
>
> Otherwise, returning NO without explicitly setting the error parameter
> will result in a dangling pointer and undefined results.
Yeah, but you're not allowed to do that. The API contract requires you to return a valid NSError object if you return NO (assuming 'outError' isn't NULL).
> I still think this is a bad thing. At a minimum, I'd consider it a
> documentation bug where the docs need to explicitly state that you
> have to assign to it in some manner if you return NO. It's possible
> that the docs may say that somewhere regarding object pointers handed
> in like this in general, but I sure didn't see it in
> NSPersistentDocument's.
It does, though:
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSDocument_Class/Reference/Reference.html
> "outError
> "On return, If the document contents could not be written, a pointer to an error object that encapsulates the reason they could not be written.
>
> "Return Value
> "YES if the document contents could be written; otherwise, NO."
It says you do have to assign it if you return NO. Well, it almost says that.
> I'm not that up on my pointer allocations. Is there some
> memory/performance reason why it isn't explicitly set to a nil first?
> Personally, if I'm using one of these methods that takes an NSError**,
> I always hand in a pointer to an explicit nil to ensure the space is
> wiped clean.
>
> Incidentally, it originally manifested for me because I have some
> fancy code to combined complex errors into a single message for
> display purposes so as not to display a "Multiple Validation Errors
> Ocurred" message. That code was what was assuming that it'd be given
> either a valid NSError or nil, because it's called very recursively
> internally elsewhere in the code.
Unfortunately, you can't use this approach with frameworks methods that have a NSError** parameter, because that's not how their API contract is designed. You can do it in methods purely of your own design, of course, but I wouldn't recommend having such an inconsistency in your application.
I sympathize with your unhappiness over this issue, but it turns out that handling errors gets very difficult very quickly if you try to automate various kinds of error handling (such as multiple error coalescing). The frameworks API design has the advantage of being both simple and consistent.
_______________________________________________
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