Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Memory Management: NSString's stringWithCString:encoding:

Suppose I'm getting a C string from some function:

char * mystring = SomeCFunction(...);

And I own this string (I'm responsible for freeing it when I'm done).

If, in Objective-C, I create an NSString * using:

NSString * mynsstring = [NSString stringWithCString:mystring 
                                           encoding:NSUTF8StringEncoding];

Am I still responsible for freeing the original C string?

I'm assuming the answer is yes, but I can't find a definitive answer in the documentation - and the functionality of the opposite method (cStringUsingEncoding), while sensical, does give me pause, because it handles the cString freeing for you.

If the answer is yes, then am I also responsible for making sure I don't free the c string before I'm done using the NSString *, or does the function copy the string for me? I ask this because the documentation for stringWithCString says it:

Returns a string containing the bytes in a given C array, interpreted according to a given encoding.

Which still leaves me wondering if it actually copied the bytes, or is just pointing at them internally (and I'm basically just doing a cast).

like image 576
Steve Avatar asked Oct 25 '11 20:10

Steve


2 Answers

It does copy the bytes.

If you don't want the bytes to be copied, you may use - (id)initWithBytesNoCopy:(void *)bytes length:(NSUInteger)length encoding:(NSStringEncoding)encoding freeWhenDone:(BOOL)flag instead.

If you use - (id)initWithBytes:(const void *)bytes length:(NSUInteger)length encoding:(NSStringEncoding)encoding, or any commodity method like stringWithCString:encoding: that itself calls this low-level method, the bytes are copied.

like image 155
AliSoftware Avatar answered Nov 15 '22 12:11

AliSoftware


The API has no idea where the pointer you pass it comes from so it doesn't know how to take ownership of it. It could be from malloc(), but it could also be an interior pointer or from mmap(), in which case free() won't work. So the API is forced to copy the data.

The only time you can pass ownership of a C buffer to a Cocoa API is if the API allows you to tell it it needs freeing. Take a look at -[NSData initWithBytesNoCopy:length:freeWhenDone:], for example.

like image 20
kperryua Avatar answered Nov 15 '22 12:11

kperryua