Объект, выпущенный с помощью CFRelease, вызывает явный сбой, но редко - PullRequest
3 голосов
/ 05 марта 2012

У меня есть следующий метод:

+ (NSString*) getMD5HashFromFile:(NSString*)filePath {
    CFStringRef md5hash = FileMD5HashCreateWithPath((CFStringRef)filePath, FileHashDefaultChunkSizeForReadingData);
    NSString *hashStr = (NSString*)md5hash;
    CFRelease(md5hash);
    return hashStr;
}

Я получал случайные сбои на Симуляторе, примерно 1 из 20-30 казней. Тот факт, что это не было последовательным, не помог мне копать глубже.

Теперь, когда я снова вижу код, кажется очевидным, что md5hash освобождается перед возвращением, что означает, что возвращенный объект недействителен. Возвращенное значение используется в другом методе непротиворечивым способом, который иногда падает, но не всегда. У меня вопрос, почему это случается редко и не всегда.

Имеет ли это какое-то отношение к сочетанию кода Obj-C и C и способа работы пулов автоматического выпуска?

Примечание: ошибка, по-видимому, исправлена ​​с помощью NSString *hashStr = [NSString stringWithString:(NSString*)md5hash], что для меня совершенно логично.

Ответы [ 3 ]

5 голосов
/ 05 марта 2012

То, что часть памяти освобождается и освобождается, не означает, что она немедленно возвращается в ОС. Ваше приложение может удерживать его в течение произвольного периода времени, основываясь на многочисленных факторах и на нескольких уровнях. В ОС иногда есть более важные дела, чем восстановление каждого фрагмента памяти, который вы отпускаете, и может потребоваться снова через полсекунды. Доступ к памяти, для которой вы вызвали free (), но технически владеете, не генерирует сигнал. Вот почему существует MallocScribble. Он перезаписывает память, которую вы освобождаете с помощью корзины (0x55), так что это становится более очевидным при использовании освобожденной памяти.

Попробуйте следующее:

char *foo = malloc(100);
strcpy(foo, "stuff");
free(foo);
printf("%s", foo);

Большую часть времени это будет работать нормально, несмотря на то, что это совершенно не так. Теперь отредактируйте схему> Диагностика и включите Scribble. Повторно запустите, и вы увидите группу «U» (0x55), указывающую, что вы читаете ерунду. Но он все равно не рухнет.

Возможно, вас заинтересует Мэтт Галлахер Посмотрите, как работает malloc на Mac , чтобы узнать больше об этой теме.

2 голосов
/ 05 марта 2012

CFRelease аргумент не должен быть NULL.

Если аргумент CFRelease равен NULL, это приведет к ошибке времени выполнения и Ваше приложение вылетит

if(md5hash)
CFRelease(md5hash);
0 голосов
/ 05 марта 2012
+(NSString*) getMD5HashFromFile:(NSString*)filePath {
    CFStringRef md5hash = FileMD5HashCreateWithPath((CFStringRef)filePath, FileHashDefaultChunkSizeForReadingData);
    NSString *hashStr = [(NSString*)md5hash copy];
    CFRelease(md5hash);
    return [hashStr autorelease];
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...