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