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:

        char buffer[] = "I HAZ A BUFFER"; 
        NSString* str = [[NSString alloc] initWithBytesNoCopy: buffer length: 
strlen(buffer) encoding: NSUTF8StringEncoding freeWhenDone: NO];

So far so good. We have an NSString that points into an ephemeral buffer I’ve 
provided.

        NSString* substr = [str substringWithRange: NSMakeRange(2, 3)]; 
        NSLog(@"substr = '%@'", substr); 

Clearly substr is equal to @“HAZ”.

        [str release];
        memset(buffer, '*', sizeof(buffer)); 

I’m now done with str, so I release it, and having released it, it’s now safe 
to destroy the buffer it was using. Right?

        NSLog(@"substr = '%@'", substr); 

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.

—Jens

* https://savannah.gnu.org/bugs/index.php?35699

_______________________________________________

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