iOS - libical / const char * - использование памяти
Я использую библиотеку libical для синтаксического анализа формата iCalendar и считывания необходимой мне информации. Пока он работает абсолютно нормально, но есть одна странная вещь в отношении ical. Это мой код:
icalcomponent *root = icalparser_parse_string([iCalData cStringUsingEncoding:NSUTF8StringEncoding]);
if (root)
{
icalcomponent *currentEvent = icalcomponent_get_first_component(root, ICAL_VEVENT_COMPONENT);
while (currentEvent)
{
while(currentProperty)
{
icalvalue *value = icalproperty_get_value(currentProperty);
char *icalString = icalvalue_as_ical_string_r(value); //seems to leak
NSString *currentValueAsString = [NSString stringWithCString:icalString
encoding:NSUTF8StringEncoding];
icalvalue_free(value);
//...
//import data
//...
icalString = nil;
currentValueAsString = nil;
icalproperty_free(currentProperty);
currentProperty = icalcomponent_get_next_property(currentEvent, ICAL_ANY_PROPERTY);
} //end while
} //end while
icalcomponent_free(currentEvent);
}
icalcomponent_free(root);
//...
Я использовал инструменты для проверки использования памяти и смог выяснить, что эта строка, похоже, протекает:
char *icalString = icalvalue_as_ical_string_r(value); //seems to leak
Если бы я скопировал и вставил эту строку 5 или 6 раз, мое использование памяти увеличилось бы приблизительно на 400 КБ и никогда больше не было бы освобождено
Там нет бесплатного метода для icalvalue_as_ical_string_r
метод, потому что он возвращает символ *..
Любые предложения, как решить эту проблему? Буду признателен за любую помощь!
РЕДАКТИРОВАТЬ
Взглянув на Apple Doc, говорит следующее:
Чтобы получить строку C из строкового объекта, рекомендуется использовать UTF8String. Это возвращает const char * с использованием строкового кодирования UTF8.
const char *cString = [@"Hello, world" UTF8String];
Полученная вами строка C принадлежит временному объекту и станет недействительной, когда произойдет автоматическое освобождение. Если вы хотите получить постоянную строку C, вы должны создать буфер и скопировать содержимое const char *, возвращаемого методом.
Но как правильно выпустить строку char * сейчас, если использовать дугу? Я пытался добавить @autorelease {...} перед циклом while, но без каких-либо усилий. Все еще увеличивается использование памяти...
2 ответа
Осторожнее с утверждением "нет бесплатного метода... потому что он возвращает символ *"; это никогда не то, что вы можете просто предположить.
В отсутствие документации вы можете посмотреть на исходный код библиотеки, чтобы увидеть, что она делает; например:
http://libical.sourcearchive.com/documentation/0.44-2/icalvalue_8c-source.html
К сожалению, эта функция может делать много разных вещей. Конечно, в некоторых случаях free()
на возвращенном буфере было бы правильно, но, возможно, это не было обеспечено в каждом случае.
Я думаю, что было бы лучше запросить правильный метод освобождения от сопровождающих библиотеки. Им нужно навести порядок в собственном беспорядке; icalvalue_as_ical_string_r()
функция имеет по крайней мере десяток случаев в switch
это может иметь разные требования освобождения.
icalvalue_as_ical_string_r
возвращает char *
потому что он сделал malloc() для вашей строки результата. Если ваш указатель не равен NULL, вы должны освободить его () после использования.