Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trouble spotting memory leak cStringUsingEncoding

Hey, I am trying to convert NSString to a C string using cStringUsingEncoding but I have a memory leak. My understanding is that cStringUsingEncoding returns a pointer to a character array that is only guaranteed to exist for the duration of the NSString object. As such you should copy its contents to another string. Here's where my problem lies...

I have a function that accepts an NSString and turns it into a C-string copy. Just for testing I ran 1,000 iterations of the following method (to ensure no leaks).

 -(void)test{
      NSString *test = [[NSString alloc] initWithString:@"Hello world!"];

      for(int i=0; i<1000; i++)
      {
           char *tmp = [self returnCopiedCString:test];

           //free memory
           free(tmp);
      }

      [test release];
 }

Pretty straight forward code... the problem is that it leaks like crazy. Now before you jump to conclusions my returnCopiedCString function works just fine. I have tested it by declaring and copying a C-string to rule out the possibility of that being an issue. Inside the function I am using the following code to convert it

 -(char *)returnCopiedCString:(NSString *)input{
      //retain input
      [input retain];

      //get length of encoded C-string
      int len = [input lengthOfBytesUsingEncoding:NSUTF8StringEncoding];

      //allocate memory for new C-string + null terminated byte
      char *toReturn = (char *)malloc((sizeof(char) * len) +1);

      //copy NSString to C-string
      strcpy(toReturn,[input cStringUsingEncoding:NSUTF8StringEncoding]);

      //release input
      [input release];

      //return pointer to newly copied string
      return toReturn;
 }

Also pretty straight forward. Then I got to thinking well maybe because I declare test outside of the for-loop, and thus its never being released, I'm leaving all of these const char* around from the cStringUsingEncoding method. so I changed the first function to be as follows:

 -(void)test{
      for(int i=0; i<1000; i++)
      {
           NSString *test = [[NSString alloc] initWithString:@"Hello world!"];

           char *tmp = [self returnCopiedCString:test];

           //free memory
           [test release];
           free(tmp);
      }
 }

but still no luck. Does anyone have any thoughts on what could be the issue here? Thanks a bunch in advance!

like image 386
tyler Avatar asked Jan 01 '26 22:01

tyler


1 Answers

From documentation:

The returned C string is guaranteed to be valid only until either the receiver is freed, or until the current autorelease pool is emptied, whichever occurs first. You should copy the C string or use getCString:maxLength:encoding: if it needs to store the C string beyond this time.

I think cStringUsingEncoding is allocating memory for the converted string to specified encoding and you don't keep the receiver so if you're not using an auto release pool, this memory is never freed.

like image 103
Eric Fortin Avatar answered Jan 03 '26 10:01

Eric Fortin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!