Hit send too soon...

> The documentation of -[NSData initWithBytesNoCopy:length:freeWhenDone:] and 
> of -[NSString initWithBytesNoCopy:length:encoding:freeWhenDone:] is unclear 
> about the case where freeWhenDone is NO. The data/string object then does not 
> take ownership of the memory buffer, so the question is: How long is the 
> caller obligated to keep the buffer intact?
>
> The two possible answers seem to be
> (a) until the caller releases the NSString object, or
> (b) forever, until the process exits (i.e. only ever use this on constant 
> buffers)
>
> I’ve been using assumption (a). Obviously I avoid storing references to the 
> string elsewhere. But as I said, the docs don’t say one way or the other, and 
> I just got burned when porting some code to GNUstep (an open-source 
> re-implementation of Cocoa), because they interpreted it according to (b). 
> Here’s a simple test case:

I hadn't thought about this problem before, but it suggests to me that
one should avoid using freeWhenDone == NO. Since supplying a
string/data object to any method or function could potentially retain
(or retain+autorelease) it, it would be exceedingly easy to create a
string/data object that has an invalid underlying buffer, thus calling
any method on this string/data object would result in a crash.

I suppose this scenario reinforces that if your method is passed a
NSString/NSData object and you need to keep it around longer than the
current stack frame, then you must copy the string/data object. I
suspect many methods don't do this though (including my own, I prefer
the caller to ensure that the string remains intact), which is why I
would avoid using freeWhenDone == NO unless a buffer is guaranteed to
last the entire process.

> Here’s the conundrum. On OS X and iOS, substr is still equal to @“HAZ”, as I 
> expected. On GNUstep it’s equal to @“***”! Why? Because GNUstep implements 
> -substringWithRange: by creating a string that points directly into the 
> parent string’s character buffer. Yes, it only does this if the parent string 
> is immutable, and the substring retains the parent string. But this means 
> that, from my perspective, my temporary buffer is now unexpectedly being used 
> by a different object whose lifespan is greater than it.
>
> I filed a bug report* saying that this substring optimization shouldn’t be 
> used if the source string uses an external buffer, just as it shouldn’t if 
> the source string is mutable. They fixed it, but some people there argue that 
> their original implementation was correct (even if not compatible with 
> Apple’s.) I’m curious, so I’m asking here to see if anyone knows for sure 
> what’s intended.
>

I agree with your suggested implementation, because if I were to write
a method that calls -substringWithRange: on a string parameter passed
to me, I would never expect that substring to become invalid until my
method or its counterparts explicitly release it. That an outsider can
affect the contents of a string created with -substringWithRange:
seems like a bug to me.

_______________________________________________

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to