Ошибка обнаружения утечки памяти cStringUsingEncoding - PullRequest
2 голосов
/ 04 августа 2010

Эй, я пытаюсь преобразовать NSString в строку C с помощью cStringUsingEncoding, но у меня утечка памяти. Насколько я понимаю, cStringUsingEncoding возвращает указатель на массив символов, который гарантированно существует только в течение срока действия объекта NSString. Таким образом, вы должны скопировать его содержимое в другую строку. Вот где моя проблема ...

У меня есть функция, которая принимает NSString и превращает ее в копию C-строки. Просто для тестирования я провел 1000 итераций следующего метода (чтобы не было утечек).

 -(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];
 }

Довольно простой код ... проблема в том, что он протекает как сумасшедший. Теперь, прежде чем делать выводы, моя функция returnCopiedCString работает просто отлично. Я проверил это, объявив и скопировав C-строку, чтобы исключить возможность возникновения проблемы. Внутри функции я использую следующий код для ее преобразования

 -(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;
 }

Также довольно прямо вперед. Тогда я хорошо подумал, может быть, потому что я объявляю test вне цикла for, и, таким образом, он никогда не освобождается, я оставляю все эти const char * вокруг метода cStringUsingEncoding. поэтому я изменил первую функцию следующим образом:

 -(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);
      }
 }

но все равно не повезло. У кого-нибудь есть мысли о том, что может быть проблемой здесь? Большое спасибо заранее!

1 Ответ

3 голосов
/ 04 августа 2010

Из документации:

Возвращенная строка C гарантированно будет действительной только до тех пор, пока не будет освобожден получатель или пока не будет очищен текущий пул автоматического выпуска, в зависимости от того, что произойдет раньше.Вам следует скопировать строку C или использовать getCString: maxLength: encoding: если необходимо сохранить строку C. после этого времени.

Я думаю, что cStringUsingEncoding выделяет память для преобразованной строки в указанной кодировке, и выне держите приемник, поэтому, если вы не используете пул автоматического выпуска, эта память никогда не освобождается.

...