У меня есть небольшое приложение, которое загружает цены на акции и прекрасно работало (в течение многих лет) до моего недавнего обновления до 10.5.7. После обновления программа вылетает по этому вызову:
NSString *currinfo = [NSString stringWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://finance.yahoo.com/d/quotes.csv?s=%@&f=l1c1p2", escsymbol]]];
Как ни странно, крушение не происходит сразу. Эта строка кода вызывается много раз, без проблем, а затем программа в конечном итоге дает сбой через 1-2 часа из-за сбоя при этом вызове.
У меня изначально был длинный пост, описывающий мои попытки исследовать эту проблему. Я получил два предложения: (i) сделать вызов асинхронным (возможно, лучше в любом случае) и (ii) использовать NSZombieEnabled, чтобы исследовать возможность того, что объект Objective C рано освобождается (этот комментарий был сделан в ответ на трассировки стека, показывающие сбой в objc_msgSend).
Я провел много времени, делая вызов асинхронным (используя [[NSURLConnection alloc] initWithRequest: theRequest делегат: self]), и это не помогло. Программа все равно провалилась, в конце концов, обычно через 10-15 минут. В течение этого интервала до сбоя многие асинхронные вызовы выполнялись без проблем, данные возвращались и т. Д. Все было хорошо. Затем программа внезапно снова упала.
Затем я включил NSZombieEnabled. Конечно же, когда программа в конце концов потерпела крах, я получил сообщение:
-[CFArray count]: message sent to deallocated instance 0x16b90bd0
"info malloc 0x16b90bd0" затем дал:
0: 0x93db810c in malloc_zone_malloc
1: 0x946bc3d1 in _CFRuntimeCreateInstance
2: 0x9464a138 in __CFArrayInit
3: 0x946cd647 in _CFStreamScheduleWithRunLoop
4: 0x932d1267 in _Z16_scheduleRStreamPKvPv
5: 0x946bf15c in CFSetApplyFunction
6: 0x932b0e2b in CFNSchedulingSetScheduleReadStream
7: 0x9331a310 in _ZN12HTTPProtocol19createAndOpenStreamEv
8: 0x9332e877 in _ZN19URLConnectionLoader24loaderScheduleOriginLoadEPK13_CFURLRequest
9: 0x9332d739 in _ZN19URLConnectionLoader26LoaderConnectionEventQueue33processAllEventsAndConsumePayloadEP20XConnectionEventInfoI12XLoaderEvent18XLoaderEventParamsEl
10: 0x9332dbdd in _ZN19URLConnectionLoader13processEventsEv
11: 0x932d8dbf in _ZN17MultiplexerSource7performEv
12: 0x946ba595 in CFRunLoopRunSpecific
13: 0x946bac78 in CFRunLoopRunInMode
14: 0x9058c530 in +[NSURLConnection(NSURLConnectionReallyInternal) _resourceLoadLoop:]
15: 0x90528e0d in -[NSThread main]
16: 0x905289b4 in __NSThread__main__
17: 0x93de8155 in _pthread_start
18: 0x93de8012 in thread_start
Я не специалист по чтению трасс стека, но разве эта трасса не указывает на проблему в коде Apple, а не в моем коде? Или я мог как-то нести ответственность за перераспределение CFArray? Есть ли способ для меня, чтобы продолжить расследование причины проблемы?
(Вот и остальная часть моего исходного поста)
Видя, что stringWithContentsOfURL
устарела, я переключился на этот код:
pathURL = [NSURL URLWithString:[NSString stringWithFormat:@"http://finance.yahoo.com/d/quotes.csv?s=%@&f=l1c1p2", escsymbol]];
NSURLRequest *request = [NSURLRequest requestWithURL:pathURL cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:30.0];
responseData = [ NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *currinfo = nil;
if ([error code]) { dNSLog((@"%@ %d %@ %@ %@", [ error domain], [ error code], [ error localizedDescription], request, @"file://localhost/etc/gettytab")); }
Это не помогло. Программа по-прежнему падает в строке sendSynchronousRequest
по истечении произвольного промежутка времени, с этой информацией в отладчике:
0 0x93db7286 in mach_msg_trap
1 0x93dbea7c in mach_msg
2 0x946ba04e in CFRunLoopRunSpecific
3 0x946bac78 in CFRunLoopRunInMode
4 0x932b53eb in CFURLConnectionSendSynchronousRequest
5 0x905dca4b in +[NSURLConnection sendSynchronousRequest:returningResponse:error:]
... и т.д.
Реальный сбой может быть в другом потоке:
0 libobjc.A.dylib 0x965c3688 objc_msgSend + 24
1 com.apple.CoreFoundation 0x946cc581 _CFStreamSignalEventSynch + 193
2 com.apple.CoreFoundation 0x946ba595 CFRunLoopRunSpecific + 3141
3 com.apple.CoreFoundation 0x946bac78 CFRunLoopRunInMode + 88
4 com.apple.Foundation 0x9058c530 +[NSURLConnection(NSURLConnectionReallyInternal) _resourceLoadLoop:] + 320
5 com.apple.Foundation 0x90528e0d -[NSThread main] + 45
6 com.apple.Foundation 0x905289b4 __NSThread__main__ + 308
7 libSystem.B.dylib 0x93de8155 _pthread_start + 321
8 libSystem.B.dylib 0x93de8012 thread_start + 34
я предполагаю, что это поток, созданный для загрузки URL. Кстати, код обработки ошибок работает нормально - когда я намеренно вызываю ошибку, отключаясь от Интернета, об ошибке просто сообщается в консоли, и программа не вылетает.
Это невероятно расстраивает. Я был бы очень рад потратить столько времени, сколько необходимо, чтобы отследить проблему, но я как бы ограничен в своих знаниях по gdb и особенно по языку ассемблера. Я не знаю, как выяснить, в чем собственно проблема кода Foundation. Сначала я подумал, что, возможно, автоматически освобожденный NSString escsymbol
каким-то образом освобождается, но отправка сообщения сохранения не помогла. Если бы это было случаем, как я мог это доказать?
Кто-нибудь еще имеет эту проблему?